@alauda-fe/common 1.4.28-beta.5 → 1.4.28

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 (174) hide show
  1. package/core/constants/constants.d.ts +0 -3
  2. package/core/services/intercept-deactivate.service.d.ts +2 -2
  3. package/core/services/time.service.d.ts +2 -8
  4. package/esm2022/abnormal-page/abnormal-page.component.mjs +1 -1
  5. package/esm2022/array-form-table/form/component.mjs +1 -1
  6. package/esm2022/array-form-table/key-value-form/component.mjs +1 -1
  7. package/esm2022/array-form-table/key-value-table/component.mjs +1 -1
  8. package/esm2022/array-form-table/string-array-form/component.mjs +1 -1
  9. package/esm2022/async-data/error-page/component.mjs +1 -1
  10. package/esm2022/async-data/page-state/component.mjs +1 -1
  11. package/esm2022/business/notification-disabled-container/component.mjs +1 -1
  12. package/esm2022/business/resource-select/exports/cluster-list/component.mjs +1 -1
  13. package/esm2022/business/resource-select/exports/cluster-selector/component.mjs +1 -1
  14. package/esm2022/business/resource-select/exports/icon/component.mjs +1 -1
  15. package/esm2022/business/resource-select/exports/mesh-group-selector/component.mjs +1 -1
  16. package/esm2022/business/resource-select/exports/namespace-list/component.mjs +1 -1
  17. package/esm2022/business/resource-select/exports/namespace-page/component.mjs +1 -1
  18. package/esm2022/business/resource-select/exports/namespace-selector/component.mjs +1 -1
  19. package/esm2022/business/resource-select/exports/project-list/component.mjs +1 -1
  20. package/esm2022/business/resource-select/exports/project-page/component.mjs +1 -1
  21. package/esm2022/business/resource-select/exports/project-selector/component.mjs +1 -1
  22. package/esm2022/business/resource-select/internals/data-grid/component.mjs +1 -1
  23. package/esm2022/business/resource-select/internals/meshgroup-list/component.mjs +1 -1
  24. package/esm2022/business/resource-select/internals/no-data/component.mjs +1 -1
  25. package/esm2022/business/resource-select/internals/resource-dashboard/component.mjs +1 -1
  26. package/esm2022/business/resource-select/internals/selector-popup/component.mjs +1 -1
  27. package/esm2022/chart/common/axis/axis-label.component.mjs +1 -1
  28. package/esm2022/chart/common/axis/x-axis-ticks.component.mjs +1 -1
  29. package/esm2022/chart/common/axis/x-axis.component.mjs +1 -1
  30. package/esm2022/chart/common/axis/x-plot-lines.component.mjs +1 -1
  31. package/esm2022/chart/common/axis/y-axis-ticks.component.mjs +1 -1
  32. package/esm2022/chart/common/axis/y-axis.component.mjs +1 -1
  33. package/esm2022/chart/common/axis/y-plot-lines.component.mjs +1 -1
  34. package/esm2022/chart/common/chart/chart.component.mjs +1 -1
  35. package/esm2022/chart/common/legend/legend.component.mjs +1 -1
  36. package/esm2022/chart/common/range-area/range-area.component.mjs +1 -1
  37. package/esm2022/chart/common/reference-area/reference-area.component.mjs +1 -1
  38. package/esm2022/chart/common/series/area-series.component.mjs +1 -1
  39. package/esm2022/chart/common/series/bar-path.component.mjs +1 -1
  40. package/esm2022/chart/common/series/bar-series.component.mjs +1 -1
  41. package/esm2022/chart/common/series/line-series.component.mjs +1 -1
  42. package/esm2022/chart/common/tooltip/tooltip.component.mjs +1 -1
  43. package/esm2022/chart/custom-template/dropdown-legend.mjs +1 -1
  44. package/esm2022/code/code-display-dialog/component.mjs +1 -1
  45. package/esm2022/code/k8s-yaml-display-dialog/component.mjs +1 -1
  46. package/esm2022/code/resource-yaml-display/component.mjs +1 -1
  47. package/esm2022/code/resource-yaml-editor/component.mjs +1 -1
  48. package/esm2022/code/yaml-sidebar/component.mjs +1 -1
  49. package/esm2022/core/components/tree/node/component.mjs +1 -1
  50. package/esm2022/core/components/tree/tree/component.mjs +1 -1
  51. package/esm2022/core/constants/constants.mjs +1 -4
  52. package/esm2022/core/directives/readonly-field.directive.mjs +1 -1
  53. package/esm2022/core/guards/intercept-deactivate.guard.mjs +2 -2
  54. package/esm2022/core/services/intercept-deactivate.service.mjs +1 -1
  55. package/esm2022/core/services/time.service.mjs +36 -13
  56. package/esm2022/custom-columns-setting/component.mjs +1 -1
  57. package/esm2022/disabled-container/disabled-container.component.mjs +1 -1
  58. package/esm2022/editable/editable.component.mjs +1 -1
  59. package/esm2022/editable-text/component.mjs +1 -1
  60. package/esm2022/exec/placeholder/component.mjs +1 -1
  61. package/esm2022/exec/terminal/component.mjs +1 -1
  62. package/esm2022/exec/terminal-group/component.mjs +1 -1
  63. package/esm2022/feature-gate-forbidden/component/component.mjs +1 -1
  64. package/esm2022/form/errors-mapper/errors-mapper-component/component.mjs +1 -1
  65. package/esm2022/form/errors-mapper/errors-mapper.directive.mjs +1 -1
  66. package/esm2022/form/labels-editor/component.mjs +1 -1
  67. package/esm2022/form/taints-editor/component.mjs +1 -1
  68. package/esm2022/form/upload-file/component.mjs +1 -1
  69. package/esm2022/form/validators/strong-password/strong-password-tooltip/component.mjs +1 -1
  70. package/esm2022/graph-canvas/components/graph-actions.component.mjs +1 -1
  71. package/esm2022/graph-canvas/components/graph-canvas.component.mjs +1 -1
  72. package/esm2022/graph-canvas/components/graph-link.component.mjs +1 -1
  73. package/esm2022/graph-canvas/components/graph-links.component.mjs +1 -1
  74. package/esm2022/grid-layout/components/grid/component.mjs +1 -1
  75. package/esm2022/grid-layout/components/grid-items/component.mjs +1 -1
  76. package/esm2022/help-document/component.mjs +1 -1
  77. package/esm2022/k8s-resource-list/footer/component.mjs +1 -1
  78. package/esm2022/k8s-shared/resource-mark/k8s-resource-mark.component.mjs +1 -1
  79. package/esm2022/k8s-shared/update-description-dialog/component.mjs +1 -1
  80. package/esm2022/k8s-shared/update-display-name-dialog/component.mjs +1 -1
  81. package/esm2022/k8s-shared/update-key-value-dialog/component.mjs +1 -1
  82. package/esm2022/lazy-component/lazy-load-component.mjs +1 -1
  83. package/esm2022/license/license-error/component.mjs +1 -1
  84. package/esm2022/list-display/component.mjs +1 -1
  85. package/esm2022/metric-chart/metric-chart.component.mjs +1 -1
  86. package/esm2022/metric-chart/metric-time-pick.mjs +1 -1
  87. package/esm2022/multi-search/action-input/component.mjs +1 -1
  88. package/esm2022/multi-search/form/component.mjs +1 -1
  89. package/esm2022/multi-search/multi-search-tags/component.mjs +1 -1
  90. package/esm2022/mutable/mosaic/mosaic.component.mjs +1 -1
  91. package/esm2022/notification/feedback-notification/component.mjs +1 -1
  92. package/esm2022/overview-banner/overview-banner.component.mjs +1 -1
  93. package/esm2022/page-guard/component/component.mjs +1 -1
  94. package/esm2022/page-scaffold/navigation/breadcrumb/breadcrumb.component.mjs +1 -1
  95. package/esm2022/page-scaffold/navigation/nav-menu/nav-item-li/nav-item-li.component.mjs +1 -1
  96. package/esm2022/page-scaffold/navigation/nav-menu/nav-item-ul/nav-item-ul.component.mjs +1 -1
  97. package/esm2022/page-scaffold/navigation/nav-menu/nav-menu.component.mjs +1 -1
  98. package/esm2022/page-scaffold/page/notices/maintenance.component.mjs +1 -1
  99. package/esm2022/page-scaffold/page/notices/notice.component.mjs +1 -1
  100. package/esm2022/page-scaffold/page/page.component.mjs +1 -1
  101. package/esm2022/page-scaffold/page/page.module.mjs +6 -5
  102. package/esm2022/page-scaffold/page-header/account-menu/component/component.mjs +1 -1
  103. package/esm2022/page-scaffold/page-header/common-layout/namespace-select/component.mjs +1 -1
  104. package/esm2022/page-scaffold/page-header/common-layout/product-select/component.mjs +1 -1
  105. package/esm2022/page-scaffold/page-header/component.mjs +1 -1
  106. package/esm2022/page-scaffold/page-header/enterprise-support-status/component.mjs +1 -1
  107. package/esm2022/page-scaffold/page-header/header-notify/component/header-notify.component.mjs +1 -1
  108. package/esm2022/page-scaffold/page-header/header-notify/component/notification-list/notification-list.component.mjs +1 -1
  109. package/esm2022/page-scaffold/page-header/help-menu/component/component.mjs +1 -1
  110. package/esm2022/page-scaffold/page-header/help-menu/module.mjs +9 -8
  111. package/esm2022/pie-derivative-chart/donut-status/component.mjs +1 -1
  112. package/esm2022/pie-derivative-chart/radial-bar/radial-bar-chart.component.mjs +1 -1
  113. package/esm2022/pod-status/component.mjs +1 -1
  114. package/esm2022/searchable-selector/component.mjs +1 -1
  115. package/esm2022/skeleton/item/component.mjs +1 -1
  116. package/esm2022/skeleton/nav-skeleton/component.mjs +1 -1
  117. package/esm2022/table/component.mjs +1 -1
  118. package/esm2022/table/module.mjs +12 -11
  119. package/esm2022/translate/constants.mjs +1 -2
  120. package/esm2022/translate/intl-format.pipes.mjs +293 -0
  121. package/esm2022/translate/public-api.mjs +4 -3
  122. package/esm2022/translate/relative-time-manager.service.mjs +87 -0
  123. package/esm2022/translate/translate.directive.mjs +5 -4
  124. package/esm2022/translate/translate.module.mjs +22 -3
  125. package/esm2022/translate/translate.pipe.mjs +7 -8
  126. package/esm2022/translate/translate.service.mjs +721 -142
  127. package/esm2022/translate/types.mjs +1 -1
  128. package/esm2022/view-chart/custom-template/dropdown-legend.mjs +1 -1
  129. package/esm2022/view-chart/legend/legend.component.mjs +1 -1
  130. package/esm2022/view-chart/view-chart.component.mjs +1 -1
  131. package/esm2022/view-zchart/custom-template/dropdown-legend.mjs +1 -1
  132. package/esm2022/view-zchart/legend/legend.component.mjs +1 -1
  133. package/esm2022/view-zchart/view-zchart.component.mjs +1 -1
  134. package/esm2022/widget/card-section/card-section.component.mjs +1 -1
  135. package/esm2022/widget/confirm-delete/confirm-delete.component.mjs +1 -1
  136. package/esm2022/widget/current-time/component.mjs +1 -1
  137. package/esm2022/widget/date-range-picker/component.mjs +1 -1
  138. package/esm2022/widget/field-set/column/component.mjs +2 -2
  139. package/esm2022/widget/field-set/group/component.mjs +1 -1
  140. package/esm2022/widget/field-set/item/component.mjs +1 -1
  141. package/esm2022/widget/foldable-block/component.mjs +1 -1
  142. package/esm2022/widget/foldable-item-in-table/component.mjs +1 -1
  143. package/esm2022/widget/loading-mask/loading-mask.component.mjs +1 -1
  144. package/esm2022/widget/password-input/component.mjs +1 -1
  145. package/esm2022/widget/relative-time/component.mjs +1 -1
  146. package/esm2022/widget/resource-label/component.mjs +1 -1
  147. package/esm2022/widget/resource-multi-select/component.mjs +1 -1
  148. package/esm2022/widget/search-panel/component.mjs +1 -1
  149. package/esm2022/widget/search-panel/search-item/component.mjs +1 -1
  150. package/esm2022/widget/status-icon/status-icon.component.mjs +1 -1
  151. package/esm2022/widget/tags-label/component.mjs +1 -1
  152. package/esm2022/widget/terminating-tag/component.mjs +1 -1
  153. package/esm2022/widget/text-ellipsis/component.mjs +1 -1
  154. package/esm2022/widget/text-with-url/component.mjs +1 -1
  155. package/esm2022/widget/zero-state/zero-state.component.mjs +1 -1
  156. package/esm2022/workload-status-icon/component.mjs +1 -1
  157. package/esm2022/xterm/xterm-terminal/xterm-terminal.component.mjs +1 -1
  158. package/esm2022/xterm/xterm.component.mjs +1 -1
  159. package/package.json +2 -2
  160. package/page-scaffold/page/page.module.d.ts +4 -3
  161. package/page-scaffold/page-header/help-menu/module.d.ts +2 -1
  162. package/table/component.d.ts +1 -1
  163. package/table/module.d.ts +2 -1
  164. package/translate/intl-format.pipes.d.ts +122 -0
  165. package/translate/public-api.d.ts +3 -2
  166. package/translate/relative-time-manager.service.d.ts +32 -0
  167. package/translate/translate.module.d.ts +4 -2
  168. package/translate/translate.pipe.d.ts +4 -5
  169. package/translate/translate.service.d.ts +292 -20
  170. package/translate/types.d.ts +16 -0
  171. package/code/resource-yaml-display/schema/component.d.ts +0 -61
  172. package/code/yaml-sidebar/yaml-examples.d.ts +0 -8
  173. package/esm2022/code/resource-yaml-display/schema/component.mjs +0 -531
  174. package/esm2022/code/yaml-sidebar/yaml-examples.mjs +0 -340
@@ -5,239 +5,818 @@ import { __decorate, __metadata } from "tslib";
5
5
  */
6
6
  import { HttpClient } from '@angular/common/http';
7
7
  import { Inject, Injectable, Optional, isDevMode, } from '@angular/core';
8
- import { get, head, isPlainObject, template } from 'lodash-es';
9
- import { EMPTY, Observable, Subject, forkJoin, throwError, catchError, filter, finalize, map, takeUntil, } from 'rxjs';
8
+ import { IntlMessageFormat } from 'intl-messageformat';
9
+ import { get, head, isPlainObject } from 'lodash-es';
10
+ import { Observable, Subject, forkJoin, throwError, EMPTY, catchError, filter, finalize, map, takeUntil, } from 'rxjs';
10
11
  import { ajax } from 'rxjs/ajax';
11
- import { API_GATEWAY, TEMPLATE_OPTIONS } from '../core/constants/constants';
12
- import { TOKEN_BASE_HREF } from '../core/public-api';
12
+ import { API_GATEWAY } from '../core/constants/constants';
13
+ import { ObservableInput, TOKEN_BASE_HREF } from '../core/public-api';
13
14
  import { isAbsoluteUrl } from '../core/utils/common';
14
- import { ObservableInput } from '../core/utils/decorators';
15
15
  import { parse } from '../core/utils/yaml';
16
16
  import { FALLBACK_LANGUAGE, LOCALE_PLACEHOLDER_REGEX, LOCALE_STORAGE, } from './constants';
17
+ import { getUserLanguage } from './i18n-config';
17
18
  import { TRANSLATE_OPTIONS, TRANSLATIONS } from './tokens';
18
19
  import * as i0 from "@angular/core";
19
20
  import * as i1 from "@angular/common/http";
21
+ /**
22
+ * 国际化翻译服务
23
+ *
24
+ * 特性:
25
+ * - 支持多层级翻译优先级(远程翻译 > 手动添加翻译 > 配置翻译)
26
+ * - 支持动态语言切换
27
+ * - 支持 ICU Message Format 模板插值
28
+ * - 支持宽松模式语言匹配
29
+ * - 支持异步远程翻译加载
30
+ */
20
31
  export class TranslateService {
32
+ /** 获取支持的语言列表 */
21
33
  get locales() {
22
34
  return this.options.locales;
23
35
  }
36
+ /** 获取回退语言 */
24
37
  get fallbackLocale() {
25
38
  return this.options.fallbackLocale;
26
39
  }
27
40
  constructor(http, baseHref, options, translationList) {
28
41
  this.http = http;
29
42
  this.baseHref = baseHref;
30
- this.translationsAdded$ = new Subject();
43
+ /** 翻译添加通知流 */
44
+ this.translationsAdded$$ = new Subject();
45
+ this.translationsAdded$ = this.translationsAdded$$.asObservable();
46
+ /** 组件销毁通知流 */
31
47
  this.destroy$$ = new Subject();
48
+ /** 本地翻译列表(优先级:后加入的优先级更高) */
32
49
  this.translationsList = [];
50
+ /** 远程翻译列表(优先级最高) */
33
51
  this.remoteTranslationsList = [];
34
- this.locale = options?.locale || navigator.language;
52
+ // 初始化语言环境
53
+ this.locale = this.getInitialLocale(options);
54
+ // 初始化配置选项
35
55
  this.options = {
36
56
  locales: [this.locale],
37
57
  fallbackLocale: FALLBACK_LANGUAGE,
58
+ loose: false,
38
59
  ...options,
39
60
  };
40
- this.translationsList = [
41
- options?.translations,
42
- ...(translationList || []),
43
- ].filter(Boolean);
44
- if (options?.remoteUrl) {
45
- if (Array.isArray(options.remoteUrl)) {
46
- options.remoteUrl.forEach(url => this.addRemoteTranslations(url));
47
- }
48
- else {
49
- this.addRemoteTranslations(options.remoteUrl);
50
- }
51
- }
61
+ // 初始化翻译列表
62
+ this.translationsList = this.getInitializeTranslations(options, translationList);
63
+ // 加载远程翻译
64
+ this.loadRemoteTranslations(options);
52
65
  }
66
+ /**
67
+ * 组件销毁清理
68
+ */
53
69
  ngOnDestroy() {
54
70
  this.destroy$$.next();
55
71
  this.destroy$$.complete();
56
72
  }
57
73
  /**
58
- * @param key - 翻译key
59
- * @param data - 根据翻译上下文数据获取翻译内容,翻译项不存在直接返回 key 文本
60
- * @param ignoreNonExist - 开发环境是否忽视不存在的翻译项
74
+ * 获取翻译文本并进行模板插值
75
+ * 自动将传统 {{ key }} 语法转换为 ICU {key} 格式进行解析
76
+ * 同时支持原生 ICU Message Format 语法
77
+ * @param key - 翻译键或翻译对象
78
+ * @param data - 模板数据(支持基本类型、Date、对象和数组)
79
+ * @returns 翻译后的文本
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * // 对象参数(推荐)
84
+ * translate.get('hello', { name: 'World' }) // 模板: "Hello {name}"
85
+ *
86
+ * // 基本类型参数(自动转换为 {value})
87
+ * translate.get('welcome', 'John') // 模板: "Welcome {value}"
88
+ *
89
+ * // ICU 格式(数字)
90
+ * translate.get('itemCount', { count: 5 })
91
+ *
92
+ * // ICU 格式(日期,默认本地化)
93
+ * translate.get('createdAt', { date: new Date() })
94
+ * ```
61
95
  */
62
96
  get(key, data) {
63
97
  const translation = this.getRaw(key);
64
- if (data != null && typeof data !== 'object') {
65
- data = [data];
98
+ if (data == null) {
99
+ return translation;
66
100
  }
67
101
  try {
68
- return template(translation, TEMPLATE_OPTIONS)(data);
102
+ // 将传统的 {{ key }} 语法转换为 ICU {key} 格式
103
+ const icuMessage = this.convertToIcuFormat(translation);
104
+ // 将数据转换为 ICU 兼容的格式
105
+ const icuData = this.normalizeAndConvertToIcuData(data);
106
+ return this.formatIcuMessage(icuMessage, icuData);
69
107
  }
70
- catch {
71
- // eslint-disable-next-line no-console
72
- console[isDevMode() ? 'error' : 'warn'](`The translation key '${key}' is missing the necessary parameters.`);
108
+ catch (error) {
109
+ this.handleTemplateError(key, error);
110
+ return translation;
73
111
  }
74
112
  }
75
113
  /**
76
- * 直接返回翻译文本模板
77
- * @param key - 翻译key
78
- * @param ignoreNonExist - 开发环境是否忽视不存在的翻译项
114
+ * 获取原始翻译文本模板(不进行插值处理)
115
+ * @param key - 翻译键或翻译对象
116
+ * @returns 原始翻译模板文本
79
117
  */
80
118
  getRaw(key) {
81
- return typeof key === 'string'
82
- ? this._get(key)
83
- : this._getValue(key);
119
+ if (typeof key === 'string') {
120
+ return this.getTranslationByKey(key);
121
+ }
122
+ // 当key是Translation对象时,获取当前语言的翻译值
123
+ const value = this.getTranslationByObject(key);
124
+ // 如果找到值则返回字符串形式,否则返回JSON字符串表示
125
+ if (value !== undefined) {
126
+ return value === null ? 'null' : String(value);
127
+ }
128
+ // 如果没有找到翻译,返回JSON字符串形式
129
+ return JSON.stringify(key);
84
130
  }
85
131
  /**
86
- * 根据 `locales` 循环切换当前区域设置
132
+ * 切换到下一个支持的语言环境
87
133
  */
88
134
  toggleLocale() {
89
- const index = this.options.locales.indexOf(this.locale);
90
- if (index === -1) {
91
- if (isDevMode()) {
92
- throw new TypeError('`locales` has not been initialized correctly');
93
- }
135
+ const currentIndex = this.options.locales.indexOf(this.locale);
136
+ if (currentIndex === -1) {
137
+ this.handleInvalidLocale();
94
138
  return;
95
139
  }
96
- const nextLocale = this.options.locales[index === this.options.locales.length - 1 ? 0 : index + 1];
97
- if (!nextLocale || this.locale === nextLocale) {
98
- return;
140
+ const nextIndex = (currentIndex + 1) % this.options.locales.length;
141
+ const nextLocale = this.options.locales[nextIndex];
142
+ if (nextLocale && nextLocale !== this.locale) {
143
+ this.setLocale(nextLocale);
99
144
  }
100
- this.setLocale(nextLocale);
101
145
  }
146
+ /**
147
+ * 设置当前语言环境
148
+ * @param locale - 要设置的语言环境
149
+ */
102
150
  setLocale(locale) {
151
+ if (!this.isValidLocale(locale)) {
152
+ if (isDevMode()) {
153
+ console.warn(`Invalid locale: ${locale}. Supported locales: ${this.options.locales.join(', ')}`);
154
+ }
155
+ return;
156
+ }
103
157
  localStorage.setItem(LOCALE_STORAGE, locale);
104
158
  this.locale = locale;
105
159
  }
106
160
  /**
107
- * 手动添加语言包
161
+ * 手动添加翻译包
162
+ * @param translations - 要添加的翻译包
108
163
  */
109
164
  addTranslations(translations) {
110
- this.translationsList.unshift(Object.freeze(translations));
111
- this.translationsAdded$.next();
165
+ if (!translations || typeof translations !== 'object') {
166
+ if (isDevMode()) {
167
+ console.warn('Invalid translations object provided');
168
+ }
169
+ return;
170
+ }
171
+ // 开发模式下检查重复翻译
172
+ if (isDevMode() && this.translationsList.length > 0) {
173
+ this.checkForDuplicateTranslations(translations);
174
+ }
175
+ this.translationsList.push(translations);
176
+ this.translationsAdded$$.next();
112
177
  }
113
178
  /**
114
- * 手动添加语言包
179
+ * 添加远程翻译包
180
+ * @param remoteUrl - 远程翻译文件URL
115
181
  */
116
182
  addRemoteTranslations(remoteUrl) {
117
183
  if (!remoteUrl) {
118
184
  return;
119
185
  }
120
- remoteUrl = head(remoteUrl.split(/#/));
121
- const isAbsolute = isAbsoluteUrl(remoteUrl);
122
- const isApiGateWayRequest = remoteUrl.startsWith(API_GATEWAY);
123
- if (isDevMode()) {
124
- let errorMessage;
125
- if (!isAbsolute && (!this.baseHref || !isAbsoluteUrl(this.baseHref))) {
126
- errorMessage = 'absolute base href is required for relative remote url';
186
+ const normalizedUrl = this.normalizeRemoteUrl(remoteUrl);
187
+ const request$ = this.createRemoteTranslationRequest(normalizedUrl);
188
+ request$
189
+ .pipe(takeUntil(this.destroy$$), finalize(() => {
190
+ this.translationsAdded$$.next();
191
+ }))
192
+ .subscribe({
193
+ next: remoteTranslations => {
194
+ if (remoteTranslations) {
195
+ this.remoteTranslationsList.push(remoteTranslations);
196
+ }
197
+ },
198
+ error: error => {
199
+ if (isDevMode()) {
200
+ console.error(`Failed to load remote translations from ${remoteUrl}:`, error);
201
+ }
202
+ },
203
+ });
204
+ }
205
+ fetchTranslation(remoteUrl, locale) {
206
+ this.validateFetchTranslationParams(remoteUrl, locale);
207
+ const targetUrl = locale
208
+ ? remoteUrl.replace(LOCALE_PLACEHOLDER_REGEX, locale)
209
+ : remoteUrl;
210
+ return this.performTranslationRequest(targetUrl);
211
+ }
212
+ /**
213
+ * 获取初始语言环境
214
+ */
215
+ getInitialLocale(options) {
216
+ return options?.locale || getUserLanguage();
217
+ }
218
+ /**
219
+ * 获取初始翻译列表
220
+ */
221
+ getInitializeTranslations(options, translationList) {
222
+ return [options?.translations, ...(translationList || [])].filter(Boolean);
223
+ }
224
+ /**
225
+ * 加载远程翻译
226
+ */
227
+ loadRemoteTranslations(options) {
228
+ if (!options?.remoteUrl)
229
+ return;
230
+ const urls = Array.isArray(options.remoteUrl)
231
+ ? options.remoteUrl
232
+ : [options.remoteUrl];
233
+ urls.forEach(url => this.addRemoteTranslations(url));
234
+ }
235
+ /**
236
+ * 转换模板数据为 ICU 兼容格式
237
+ * @param data - 模板数据
238
+ * @returns ICU 兼容的数据对象
239
+ */
240
+ normalizeAndConvertToIcuData(data) {
241
+ if (data == null) {
242
+ return {};
243
+ }
244
+ // 如果是纯对象,直接转换其属性
245
+ if (this.isPlainTemplateObject(data)) {
246
+ return this.convertObjectToIcuData(data);
247
+ }
248
+ // 基本类型、数组、Date等包装为 { value: data }
249
+ return { value: this.convertValueToIcuValue(data) };
250
+ }
251
+ /**
252
+ * 检查是否为纯模板对象(不是数组、Date等特殊对象)
253
+ */
254
+ isPlainTemplateObject(data) {
255
+ return (typeof data === 'object' &&
256
+ data !== null &&
257
+ !Array.isArray(data) &&
258
+ !(data instanceof Date) &&
259
+ data.constructor === Object);
260
+ }
261
+ /**
262
+ * 转换对象的所有属性为 ICU 兼容值
263
+ */
264
+ convertObjectToIcuData(obj) {
265
+ const result = {};
266
+ for (const [key, value] of Object.entries(obj)) {
267
+ if (value != null) {
268
+ result[key] = this.convertValueToIcuValue(value);
269
+ }
270
+ }
271
+ return result;
272
+ }
273
+ /**
274
+ * 将单个值转换为 ICU 兼容类型
275
+ * 按照 ICU MessageFormat 规范,只支持 string | number | Date
276
+ */
277
+ convertValueToIcuValue(value) {
278
+ // ICU 原生支持的类型直接返回
279
+ if (typeof value === 'string' || typeof value === 'number') {
280
+ return value;
281
+ }
282
+ if (value instanceof Date) {
283
+ return value;
284
+ }
285
+ // 其他类型转为字符串
286
+ if (typeof value === 'boolean') {
287
+ return String(value);
288
+ }
289
+ if (Array.isArray(value)) {
290
+ // 简单数组转为逗号分隔的字符串
291
+ return value.map(item => String(item ?? '')).join(', ');
292
+ }
293
+ if (value === null) {
294
+ return 'null';
295
+ }
296
+ if (value === undefined) {
297
+ return '';
298
+ }
299
+ // 对象转为 JSON 字符串
300
+ if (typeof value === 'object') {
301
+ try {
302
+ return JSON.stringify(value);
127
303
  }
128
- else if (remoteUrl.split('?')[0].includes('./')) {
129
- errorMessage =
130
- 'do not use any dot with slash for relative url which should always base from base href';
304
+ catch {
305
+ return String(value);
131
306
  }
132
- if (errorMessage) {
133
- throw new TypeError(errorMessage);
307
+ }
308
+ return String(value);
309
+ }
310
+ /**
311
+ * 处理模板错误
312
+ */
313
+ handleTemplateError(key, error) {
314
+ const keyStr = typeof key === 'string' ? key : '[object]';
315
+ const message = `The translation key '${keyStr}' is missing the necessary parameters.`;
316
+ if (isDevMode()) {
317
+ console.error(message, error);
318
+ }
319
+ else {
320
+ console.warn(message, error);
321
+ }
322
+ }
323
+ /**
324
+ * 将传统的 {{ key }} 语法转换为 ICU {key} 格式
325
+ * 同时保持已有的 ICU 格式不变
326
+ * @param message - 原始消息模板
327
+ * @returns 转换后的 ICU 格式消息
328
+ */
329
+ convertToIcuFormat(message) {
330
+ // 将 {{ key }} 转换为 {key}
331
+ // 支持空格:{{ key }} -> {key},但去掉内部的空格
332
+ return message.replace(/\{\{([^}]+)\}\}/g, (_, content) => {
333
+ return `{${content.trim()}}`;
334
+ });
335
+ }
336
+ /**
337
+ * 使用 ICU message format 格式化文本
338
+ */
339
+ formatIcuMessage(message, icuData) {
340
+ try {
341
+ const messageFormat = new IntlMessageFormat(message, this.locale);
342
+ return messageFormat.format(icuData);
343
+ }
344
+ catch (error) {
345
+ if (isDevMode()) {
346
+ console.warn(`ICU message formatting failed for "${message}":`, error);
134
347
  }
348
+ // 降级处理:返回原始消息
349
+ return message;
135
350
  }
136
- if (!isAbsolute && !isApiGateWayRequest) {
137
- remoteUrl =
138
- (this.baseHref.endsWith('/') ? this.baseHref : this.baseHref + '/') +
139
- remoteUrl;
140
- }
141
- (LOCALE_PLACEHOLDER_REGEX.test(remoteUrl)
142
- ? forkJoin(this.options.locales.map(locale => this.fetchTranslation(remoteUrl, locale).pipe(catchError(error => {
143
- if (this.options.loose) {
144
- const looseLocale = this._getLooseLocale(locale);
145
- if (locale !== looseLocale &&
146
- !this.options.locales.includes(looseLocale)) {
147
- return this.fetchTranslation(remoteUrl, looseLocale);
148
- }
149
- }
150
- return isDevMode() ? throwError(() => error) : EMPTY;
151
- }), filter(isPlainObject), map((translation) => ({
152
- [locale]: translation,
153
- }))))).pipe(map(_ => _.reduce(Object.assign)))
154
- : this.fetchTranslation(remoteUrl).pipe(catchError(error => (isDevMode() ? throwError(() => error) : EMPTY))))
155
- .pipe(takeUntil(this.destroy$$), finalize(() => {
156
- this.translationsAdded$.next();
157
- }))
158
- .subscribe(remoteTranslations => {
159
- if (!remoteTranslations) {
160
- return;
351
+ }
352
+ /**
353
+ * 格式化数字
354
+ * @param value - 要格式化的数字
355
+ * @param options - 格式化选项
356
+ * @returns 格式化后的数字字符串
357
+ *
358
+ * @example
359
+ * formatNumber(1234.56) // "1,234.56"
360
+ * formatNumber(0.85, { style: 'percent' }) // "85%"
361
+ * formatNumber(1234.56, { style: 'currency', currency: 'CNY' }) // "¥1,234.56"
362
+ */
363
+ formatNumber(value, options = {}) {
364
+ try {
365
+ return new Intl.NumberFormat(this.locale, options).format(value);
366
+ }
367
+ catch (error) {
368
+ if (isDevMode()) {
369
+ console.warn(`Number formatting failed for value ${value}:`, error);
161
370
  }
162
- this.remoteTranslationsList.unshift(Object.freeze(remoteTranslations));
371
+ return value.toString();
372
+ }
373
+ }
374
+ /**
375
+ * 格式化货币
376
+ * @param value - 要格式化的金额
377
+ * @param currency - 货币代码,默认为 CNY
378
+ * @param options - 其他格式化选项
379
+ * @returns 格式化后的货币字符串
380
+ *
381
+ * @example
382
+ * formatCurrency(1234.56) // en-US: "CN¥1,234.56", zh-CN: "¥1,234.56"
383
+ * formatCurrency(1234.56, 'USD') // en-US: "$1,234.56", zh-CN: "US$1,234.56"
384
+ */
385
+ formatCurrency(value, currency = 'CNY', options = {}) {
386
+ return this.formatNumber(value, {
387
+ style: 'currency',
388
+ currency,
389
+ ...options,
163
390
  });
164
391
  }
165
- fetchTranslation(remoteUrl, locale) {
166
- if (isDevMode() && LOCALE_PLACEHOLDER_REGEX.test(remoteUrl) && !locale) {
167
- throw new TypeError('`locale` is required sine the provided remote url contains locale placeholder');
392
+ /**
393
+ * 格式化百分比
394
+ * @param value - 要格式化的值(0.85 表示 85%)
395
+ * @param options - 格式化选项
396
+ * @returns 格式化后的百分比字符串
397
+ *
398
+ * @example
399
+ * formatPercent(0.85) // "85%"
400
+ * formatPercent(0.8567, { minimumFractionDigits: 2 }) // "85.67%"
401
+ */
402
+ formatPercent(value, options = {}) {
403
+ return this.formatNumber(value, {
404
+ style: 'percent',
405
+ ...options,
406
+ });
407
+ }
408
+ /**
409
+ * 格式化日期
410
+ * @param date - 要格式化的日期
411
+ * @param options - Intl.DateTimeFormatOptions 格式配置
412
+ * @returns 格式化后的日期字符串
413
+ *
414
+ * @example
415
+ * formatDate(new Date()) // en-US: "01/01/2025", zh-CN: "2025/01/01"
416
+ * formatDate(new Date(), { dateStyle: 'full' }) // "2024年8月20日星期二"
417
+ * formatDate(new Date(), { year: 'numeric', month: '2-digit', day: '2-digit' }) // 根据locale格式化
418
+ * formatDate(new Date(), { year: 'numeric', month: 'long' }) // "2024年8月"
419
+ */
420
+ formatDate(date, options = {
421
+ year: 'numeric',
422
+ month: '2-digit',
423
+ day: '2-digit',
424
+ }) {
425
+ try {
426
+ const dateObj = new Date(date);
427
+ if (isNaN(dateObj.getTime())) {
428
+ throw new Error('Invalid date');
429
+ }
430
+ return this.formatDateByOptions(dateObj, options);
431
+ }
432
+ catch (error) {
433
+ if (isDevMode()) {
434
+ console.warn(`Date formatting failed for date ${date}:`, error);
435
+ }
436
+ return String(date);
168
437
  }
169
- const isJSON = remoteUrl.endsWith('.json');
438
+ }
439
+ /**
440
+ * 格式化日期和时间
441
+ * @param date - 要格式化的日期时间
442
+ * @param options - Intl.DateTimeFormatOptions 格式配置
443
+ * @returns 格式化后的日期时间字符串
444
+ *
445
+ * @example
446
+ * formatDateTime(new Date()) // en-US: "01/01/2025, 14:30:00", zh-CN: "2025/01/01 14:30:00"
447
+ * formatDateTime(new Date(), { dateStyle: 'medium', timeStyle: 'short' }) // "2024年8月20日 14:30"
448
+ * formatDateTime(new Date(), { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }) // 根据locale格式化
449
+ */
450
+ formatDateTime(date, options = {
451
+ year: 'numeric',
452
+ month: '2-digit',
453
+ day: '2-digit',
454
+ hour: '2-digit',
455
+ minute: '2-digit',
456
+ second: '2-digit',
457
+ hour12: false,
458
+ }) {
459
+ return this.formatDate(date, options);
460
+ }
461
+ formatRelativeTime(value, unitOrOptions, options = { numeric: 'auto' }) {
462
+ try {
463
+ let finalValue;
464
+ let finalUnit;
465
+ let finalOptions;
466
+ if (value instanceof Date) {
467
+ // 自动计算时间差和单位
468
+ const { value: calculatedValue, unit: calculatedUnit } = this.calculateRelativeTime(value);
469
+ finalValue = calculatedValue;
470
+ finalUnit = calculatedUnit;
471
+ finalOptions =
472
+ unitOrOptions || options;
473
+ }
474
+ else {
475
+ // 使用提供的数值和单位
476
+ finalValue = value;
477
+ finalUnit = unitOrOptions;
478
+ finalOptions = options;
479
+ }
480
+ return new Intl.RelativeTimeFormat(this.locale, finalOptions).format(finalValue, finalUnit);
481
+ }
482
+ catch (error) {
483
+ if (isDevMode()) {
484
+ console.warn(`Relative time formatting failed for ${value}:`, error);
485
+ }
486
+ return value instanceof Date
487
+ ? value.toLocaleString(this.locale)
488
+ : `${value}`;
489
+ }
490
+ }
491
+ /**
492
+ * 根据日期计算相对时间差值和最合适的单位
493
+ * @param date - 目标日期
494
+ * @returns 包含时间差值和单位的对象
495
+ */
496
+ calculateRelativeTime(date) {
497
+ const now = new Date();
498
+ const diffMs = date.getTime() - now.getTime();
499
+ const absDiffMs = Math.abs(diffMs);
500
+ // 时间单位阈值(毫秒)
501
+ const MINUTE_MS = 60 * 1000;
502
+ const HOUR_MS = 60 * MINUTE_MS;
503
+ const DAY_MS = 24 * HOUR_MS;
504
+ // 根据时间差选择合适的单位,最大单位为day
505
+ if (absDiffMs >= DAY_MS) {
506
+ return {
507
+ value: Math.round(diffMs / DAY_MS),
508
+ unit: 'day',
509
+ };
510
+ }
511
+ if (absDiffMs >= HOUR_MS) {
512
+ return {
513
+ value: Math.round(diffMs / HOUR_MS),
514
+ unit: 'hour',
515
+ };
516
+ }
517
+ if (absDiffMs >= MINUTE_MS) {
518
+ return {
519
+ value: Math.round(diffMs / MINUTE_MS),
520
+ unit: 'minute',
521
+ };
522
+ }
523
+ return {
524
+ value: Math.round(diffMs / 1000),
525
+ unit: 'second',
526
+ };
527
+ }
528
+ /**
529
+ * 根据日期格式配置格式化日期
530
+ * 使用标准 Intl.DateTimeFormatOptions 确保格式可预测性
531
+ */
532
+ formatDateByOptions(date, options) {
533
+ try {
534
+ return new Intl.DateTimeFormat(this.locale, options).format(date);
535
+ }
536
+ catch (error) {
537
+ if (isDevMode()) {
538
+ console.warn(`Date formatting failed:`, error);
539
+ }
540
+ return date.toISOString();
541
+ }
542
+ }
543
+ /**
544
+ * 通过字符串键获取翻译
545
+ */
546
+ getTranslationByKey(key) {
547
+ return this.resolveTranslation(key);
548
+ }
549
+ /**
550
+ * 通过翻译对象获取翻译值
551
+ */
552
+ getTranslationByObject(translationObj) {
553
+ return this.getTranslationValue(translationObj, this.locale);
554
+ }
555
+ /**
556
+ * 处理无效语言环境
557
+ */
558
+ handleInvalidLocale() {
559
+ if (isDevMode()) {
560
+ throw new TypeError('`locales` has not been initialized correctly');
561
+ }
562
+ }
563
+ /**
564
+ * 验证语言环境是否有效
565
+ */
566
+ isValidLocale(locale) {
567
+ return this.options.locales.includes(locale);
568
+ }
569
+ /**
570
+ * 检查重复翻译(开发模式)
571
+ */
572
+ checkForDuplicateTranslations(newTranslations) {
573
+ for (const existingTranslations of this.translationsList) {
574
+ Object.keys(newTranslations).forEach(locale => {
575
+ if (existingTranslations[locale]) {
576
+ this.compareTranslationKeys(locale, newTranslations[locale], existingTranslations[locale]);
577
+ }
578
+ });
579
+ }
580
+ }
581
+ /**
582
+ * 标准化远程URL
583
+ */
584
+ normalizeRemoteUrl(remoteUrl) {
585
+ remoteUrl = this.cleanUrl(remoteUrl);
586
+ const isAbsolute = isAbsoluteUrl(remoteUrl);
170
587
  const isApiGateWayRequest = remoteUrl.startsWith(API_GATEWAY);
171
- const url = locale
172
- ? remoteUrl.replace(LOCALE_PLACEHOLDER_REGEX, locale)
173
- : remoteUrl;
588
+ // 开发模式下进行URL验证
589
+ if (isDevMode()) {
590
+ this.validateRemoteUrl(remoteUrl, isAbsolute);
591
+ }
592
+ // 相对URL转换为绝对URL
593
+ if (!isAbsolute && !isApiGateWayRequest) {
594
+ const baseUrl = this.baseHref.endsWith('/')
595
+ ? this.baseHref
596
+ : `${this.baseHref}/`;
597
+ return `${baseUrl}${remoteUrl}`;
598
+ }
599
+ return remoteUrl;
600
+ }
601
+ /**
602
+ * 清理URL(移除hash片段)
603
+ */
604
+ cleanUrl(url) {
605
+ return head(url.split(/#/)) || url;
606
+ }
607
+ /**
608
+ * 验证远程URL(开发模式)
609
+ */
610
+ validateRemoteUrl(remoteUrl, isAbsolute) {
611
+ if (!isAbsolute && (!this.baseHref || !isAbsoluteUrl(this.baseHref))) {
612
+ throw new TypeError('absolute base href is required for relative remote url');
613
+ }
614
+ if (remoteUrl.split('?')[0].includes('./')) {
615
+ throw new TypeError('do not use any dot with slash for relative url which should always base from base href');
616
+ }
617
+ }
618
+ /**
619
+ * 创建远程翻译请求
620
+ */
621
+ createRemoteTranslationRequest(normalizedUrl) {
622
+ if (LOCALE_PLACEHOLDER_REGEX.test(normalizedUrl)) {
623
+ return this.createMultiLocaleRequest(normalizedUrl);
624
+ }
625
+ return this.createSingleLocaleRequest(normalizedUrl);
626
+ }
627
+ /**
628
+ * 创建多语言请求
629
+ */
630
+ createMultiLocaleRequest(urlTemplate) {
631
+ const requests = this.options.locales.map(locale => this.fetchTranslation(urlTemplate, locale).pipe(catchError(error => {
632
+ if (this.options.loose) {
633
+ const looseLocale = this.extractLooseLocale(locale);
634
+ if (locale !== looseLocale &&
635
+ !this.options.locales.includes(looseLocale)) {
636
+ return this.fetchTranslation(urlTemplate, looseLocale);
637
+ }
638
+ }
639
+ return isDevMode() ? throwError(() => error) : EMPTY;
640
+ }), filter(isPlainObject), map((translation) => ({ [locale]: translation }))));
641
+ return forkJoin(requests).pipe(map(results => results.reduce((acc, curr) => Object.assign(acc, curr), {})));
642
+ }
643
+ /**
644
+ * 创建单语言请求
645
+ */
646
+ createSingleLocaleRequest(url) {
647
+ return this.performTranslationRequest(url).pipe(catchError(error => (isDevMode() ? throwError(() => error) : EMPTY)));
648
+ }
649
+ /**
650
+ * 执行翻译请求
651
+ */
652
+ performTranslationRequest(url) {
653
+ const isJSON = url.endsWith('.json');
654
+ const isApiGateWayRequest = url.startsWith(API_GATEWAY);
174
655
  const responseType = isJSON ? 'json' : 'text';
175
656
  if (isApiGateWayRequest) {
176
657
  return this.http
177
658
  .request('GET', url, { responseType })
178
659
  .pipe(map(body => (isJSON ? body : parse(body))));
179
660
  }
180
- return ajax({
181
- url,
182
- responseType,
183
- }).pipe(map(({ response }) => (isJSON ? response : parse(response))));
661
+ return ajax({ url, responseType }).pipe(map(({ response }) => (isJSON ? response : parse(response))));
184
662
  }
185
- _getLooseLocale(locale) {
186
- return head(locale.split(/[_-]/));
663
+ /**
664
+ * 验证fetchTranslation参数
665
+ */
666
+ validateFetchTranslationParams(remoteUrl, locale) {
667
+ if (isDevMode() && LOCALE_PLACEHOLDER_REGEX.test(remoteUrl) && !locale) {
668
+ throw new TypeError('`locale` is required since the provided remote url contains locale placeholder');
669
+ }
187
670
  }
188
- _getValue(source, locale = this.locale) {
189
- if (!source) {
190
- return;
671
+ /**
672
+ * 解析翻译文本
673
+ */
674
+ resolveTranslation(key, locale = this.locale) {
675
+ // 优先从远程翻译中查找
676
+ let value = this.searchInTranslationsList(key, locale, this.remoteTranslationsList);
677
+ // 如果远程翻译中没有找到(undefined),则从本地翻译中查找
678
+ if (value === undefined) {
679
+ value = this.searchInTranslationsList(key, locale, this.translationsList);
680
+ }
681
+ return value ?? key;
682
+ }
683
+ /**
684
+ * 在翻译列表中搜索
685
+ */
686
+ searchInTranslationsList(key, locale, translationsList) {
687
+ if (!translationsList || translationsList.length === 0) {
688
+ return undefined;
191
689
  }
192
- let value = source[locale];
193
- if (value == null && this.options.loose) {
194
- const looseLocale = this._getLooseLocale(locale);
195
- value =
196
- locale === looseLocale
197
- ? Object.entries(source).find(([key]) => locale === this._getLooseLocale(key))?.[1]
198
- : source[looseLocale];
199
- }
200
- if (value == null && locale !== this.options.fallbackLocale) {
201
- return this._getValue(source, this.options.fallbackLocale);
202
- }
203
- return value;
204
- }
205
- _getWithFallback(key, locale = this.locale, translations) {
206
- const value = get(this._getValue(translations, locale), key);
207
- if (value != null) {
208
- if (typeof value === 'object' &&
209
- isDevMode() &&
210
- typeof get(value, Symbol.toPrimitive) !== 'function') {
211
- console.warn(`The translation for locale: \`${locale}\` and key:\`${key}\` is an object, which could be unexpected`);
690
+ // 从后往前遍历(后加入的优先级更高)
691
+ for (let i = translationsList.length - 1; i >= 0; i--) {
692
+ const value = this.searchInTranslations(key, locale, translationsList[i]);
693
+ if (value !== undefined) {
694
+ return value;
212
695
  }
213
- return String(value);
214
696
  }
697
+ return undefined;
698
+ }
699
+ /**
700
+ * 在单个翻译对象中搜索
701
+ */
702
+ searchInTranslations(key, locale, translations) {
703
+ const translationValue = this.getTranslationValue(translations, locale);
704
+ // 如果没有获取到翻译值对象(getTranslationValue已经处理了loose和fallback),直接返回
705
+ if (translationValue === undefined) {
706
+ return undefined;
707
+ }
708
+ // 获取翻译值,支持扁平和嵌套两种结构
709
+ const value = this.getTranslationFromSource(translationValue, key);
710
+ // 如果找到值(包括null值),则处理并返回
711
+ if (value !== undefined) {
712
+ this.validateTranslationValue(value, locale, key);
713
+ // null值转换为字符串'null',其他值正常转换
714
+ return value === null ? 'null' : String(value);
715
+ }
716
+ // 如果在当前语言的翻译值中找不到key,但这不是fallback语言,尝试fallback
215
717
  if (locale !== this.options.fallbackLocale) {
216
- return this._getWithFallback(key, this.options.fallbackLocale, translations);
718
+ const fallbackTranslationValue = this.getTranslationValue(translations, this.options.fallbackLocale);
719
+ if (fallbackTranslationValue !== undefined) {
720
+ const fallbackValue = this.getTranslationFromSource(fallbackTranslationValue, key);
721
+ if (fallbackValue !== undefined) {
722
+ this.validateTranslationValue(fallbackValue, this.options.fallbackLocale, key);
723
+ return fallbackValue === null ? 'null' : String(fallbackValue);
724
+ }
725
+ }
217
726
  }
727
+ return undefined;
218
728
  }
219
- _getBase(key, locale = this.locale, translationsList) {
220
- if (!translationsList || translationsList.length === 0) {
221
- return;
729
+ /**
730
+ * 从翻译源获取翻译值,支持扁平和嵌套两种结构
731
+ * @param source - 翻译源对象
732
+ * @param key - 翻译键(如 'a.b.c')
733
+ * @returns 翻译值或undefined
734
+ */
735
+ getTranslationFromSource(source, key) {
736
+ if (!source || typeof source !== 'object') {
737
+ return undefined;
222
738
  }
223
- for (let i = translationsList.length; i > 0; i--) {
224
- const value = this._getWithFallback(key, locale, translationsList[i - 1]);
225
- if (value != null) {
226
- return value;
739
+ // 1. 优先尝试扁平结构:直接查找完整的键 'a.b.c'
740
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
741
+ return source[key];
742
+ }
743
+ // 2. 再尝试嵌套结构:使用lodash.get按路径查找 a.b.c
744
+ const nestedValue = get(source, key);
745
+ if (nestedValue !== undefined) {
746
+ return nestedValue;
747
+ }
748
+ return undefined;
749
+ }
750
+ /**
751
+ * 获取指定语言的翻译值(处理loose模式和fallback逻辑)
752
+ */
753
+ getTranslationValue(source, locale = this.locale) {
754
+ if (!source) {
755
+ return undefined;
756
+ }
757
+ // 1. 首先检查精确匹配的键是否存在
758
+ if (Object.prototype.hasOwnProperty.call(source, locale)) {
759
+ return source[locale]; // 返回实际值,可能是null、undefined或其他值
760
+ }
761
+ // 2. 如果启用了宽松模式,尝试宽松匹配
762
+ if (this.options.loose) {
763
+ const looseValue = this.getLooseTranslationValue(source, locale);
764
+ if (looseValue !== undefined) {
765
+ return looseValue;
227
766
  }
228
767
  }
768
+ // 3. 如果当前语言不是fallback语言,尝试fallback语言
769
+ if (locale !== this.options.fallbackLocale) {
770
+ // 首先检查fallback语言的精确匹配
771
+ if (Object.prototype.hasOwnProperty.call(source, this.options.fallbackLocale)) {
772
+ return source[this.options.fallbackLocale];
773
+ }
774
+ // 如果启用了宽松模式,也对fallback语言进行宽松匹配
775
+ if (this.options.loose) {
776
+ const fallbackLooseValue = this.getLooseTranslationValue(source, this.options.fallbackLocale);
777
+ if (fallbackLooseValue !== undefined) {
778
+ return fallbackLooseValue;
779
+ }
780
+ }
781
+ }
782
+ return undefined;
229
783
  }
230
- _get(key, locale = this.locale) {
231
- let value = this._getBase(key, locale, this.remoteTranslationsList);
232
- if (value == null) {
233
- value = this._getBase(key, locale, this.translationsList);
784
+ /**
785
+ * 宽松模式下获取翻译值
786
+ */
787
+ getLooseTranslationValue(source, locale) {
788
+ const looseLocale = this.extractLooseLocale(locale);
789
+ if (locale === looseLocale) {
790
+ // 寻找匹配的宽松语言
791
+ const matchedEntry = Object.entries(source).find(([key]) => looseLocale === this.extractLooseLocale(key));
792
+ return matchedEntry?.[1];
234
793
  }
235
- if (value != null) {
236
- return value;
794
+ // 检查宽松语言键是否存在
795
+ if (Object.prototype.hasOwnProperty.call(source, looseLocale)) {
796
+ return source[looseLocale];
237
797
  }
238
- return key;
798
+ return undefined;
239
799
  }
240
- _compareKeys(locale, translation, prevTranslation, path = []) {
800
+ /**
801
+ * 提取宽松语言代码(如:zh-CN -> zh)
802
+ */
803
+ extractLooseLocale(locale) {
804
+ return head(locale.split(/[_-]/)) || locale;
805
+ }
806
+ /**
807
+ * 验证翻译值(开发模式)
808
+ */
809
+ validateTranslationValue(value, locale, key) {
810
+ if (isDevMode() &&
811
+ typeof value === 'object' &&
812
+ typeof get(value, Symbol.toPrimitive) !== 'function') {
813
+ console.warn(`The translation for locale: \`${locale}\` and key:\`${key}\` is an object, which could be unexpected`);
814
+ }
815
+ }
816
+ /**
817
+ * 比较翻译键(开发模式下检查重复)
818
+ */
819
+ compareTranslationKeys(locale, translation, prevTranslation, path = []) {
241
820
  if (translation == null || prevTranslation == null) {
242
821
  return;
243
822
  }
@@ -249,7 +828,7 @@ export class TranslateService {
249
828
  const valueIsPlainObject = isPlainObject(value);
250
829
  const prevValueIsPlainObject = isPlainObject(prevValue);
251
830
  if (valueIsPlainObject && prevValueIsPlainObject) {
252
- this._compareKeys(locale, value, prevValue, [...path, key]);
831
+ this.compareTranslationKeys(locale, value, prevValue, [...path, key]);
253
832
  return;
254
833
  }
255
834
  if (!valueIsPlainObject && !prevValueIsPlainObject) {
@@ -258,7 +837,7 @@ export class TranslateService {
258
837
  console.warn(`The customized translation for locale: \`${locale}\` and path: \`${outputPath}\` is duplicated with the other translation, please remove it in your translation file.`);
259
838
  }
260
839
  else {
261
- console.warn(`Two keys that the locale is \`${locale}\` and the path is \`${outputPath}\` are same, but their values are not equal , please remove one of them or change one of the keys.`);
840
+ console.warn(`Two keys that the locale is \`${locale}\` and the path is \`${outputPath}\` are same, but their values are not equal, please remove one of them or change one of the keys.`);
262
841
  }
263
842
  }
264
843
  });
@@ -287,4 +866,4 @@ __decorate([
287
866
  type: Inject,
288
867
  args: [TRANSLATIONS]
289
868
  }] }], { locale$: [] }); })();
290
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNsYXRlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWJzL2NvbW1vbi9zcmMvdHJhbnNsYXRlL3RyYW5zbGF0ZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O0dBR0c7QUFFSCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbEQsT0FBTyxFQUNMLE1BQU0sRUFDTixVQUFVLEVBRVYsUUFBUSxFQUNSLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsUUFBUSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQy9ELE9BQU8sRUFDTCxLQUFLLEVBQ0wsVUFBVSxFQUNWLE9BQU8sRUFDUCxRQUFRLEVBQ1IsVUFBVSxFQUNWLFVBQVUsRUFDVixNQUFNLEVBQ04sUUFBUSxFQUNSLEdBQUcsRUFDSCxTQUFTLEdBQ1YsTUFBTSxNQUFNLENBQUM7QUFDZCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRWpDLE9BQU8sRUFBRSxXQUFXLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUM1RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDckQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFM0MsT0FBTyxFQUNMLGlCQUFpQixFQUNqQix3QkFBd0IsRUFDeEIsY0FBYyxHQUNmLE1BQU0sYUFBYSxDQUFDO0FBQ3JCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxZQUFZLEVBQUUsTUFBTSxVQUFVLENBQUM7OztBQVUzRCxNQUFNLE9BQU8sZ0JBQWdCO0lBYzNCLElBQUksT0FBTztRQUNULE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUM7SUFDOUIsQ0FBQztJQUVELElBQUksY0FBYztRQUNoQixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDO0lBQ3JDLENBQUM7SUFFRCxZQUNtQixJQUFnQixFQUVoQixRQUFnQixFQUdqQyxPQUF5QixFQUNTLGVBQStCO1FBTmhELFNBQUksR0FBSixJQUFJLENBQVk7UUFFaEIsYUFBUSxHQUFSLFFBQVEsQ0FBUTtRQXhCMUIsdUJBQWtCLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztRQUVqQyxjQUFTLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztRQUV4QyxxQkFBZ0IsR0FBa0MsRUFBRSxDQUFDO1FBQ3JELDJCQUFzQixHQUFrQyxFQUFFLENBQUM7UUF5QmxFLElBQUksQ0FBQyxNQUFNLEdBQUcsT0FBTyxFQUFFLE1BQU0sSUFBSSxTQUFTLENBQUMsUUFBUSxDQUFDO1FBQ3BELElBQUksQ0FBQyxPQUFPLEdBQUc7WUFDYixPQUFPLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO1lBQ3RCLGNBQWMsRUFBRSxpQkFBaUI7WUFDakMsR0FBRyxPQUFPO1NBQ1gsQ0FBQztRQUVGLElBQUksQ0FBQyxnQkFBZ0IsR0FBRztZQUN0QixPQUFPLEVBQUUsWUFBWTtZQUNyQixHQUFHLENBQUMsZUFBZSxJQUFJLEVBQUUsQ0FBQztTQUMzQixDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVsQixJQUFJLE9BQU8sRUFBRSxTQUFTLEVBQUUsQ0FBQztZQUN2QixJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7Z0JBQ3JDLE9BQU8sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDcEUsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDaEQsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUM1QixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEdBQUcsQ0FBQyxHQUFpQixFQUFFLElBQWM7UUFDbkMsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNyQyxJQUFJLElBQUksSUFBSSxJQUFJLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDN0MsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDaEIsQ0FBQztRQUNELElBQUksQ0FBQztZQUNILE9BQU8sUUFBUSxDQUFDLFdBQVcsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDLElBQWMsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxzQ0FBc0M7WUFDdEMsT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUNyQyx3QkFBd0IsR0FBRyx3Q0FBd0MsQ0FDcEUsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILE1BQU0sQ0FBQyxHQUFpQjtRQUN0QixPQUFPLE9BQU8sR0FBRyxLQUFLLFFBQVE7WUFDNUIsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO1lBQ2hCLENBQUMsQ0FBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBWSxDQUFDO0lBQ3RDLENBQUM7SUFFRDs7T0FFRztJQUNILFlBQVk7UUFDVixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3hELElBQUksS0FBSyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDakIsSUFBSSxTQUFTLEVBQUUsRUFBRSxDQUFDO2dCQUNoQixNQUFNLElBQUksU0FBUyxDQUFDLDhDQUE4QyxDQUFDLENBQUM7WUFDdEUsQ0FBQztZQUNELE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxVQUFVLEdBQ2QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQ2xCLEtBQUssS0FBSyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxDQUFDLENBQzFELENBQUM7UUFFSixJQUFJLENBQUMsVUFBVSxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDOUMsT0FBTztRQUNULENBQUM7UUFFRCxJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzdCLENBQUM7SUFFRCxTQUFTLENBQUMsTUFBYztRQUN0QixZQUFZLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUM3QyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztJQUN2QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxlQUFlLENBQUMsWUFBMEI7UUFDeEMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUM7UUFDM0QsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksRUFBRSxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7T0FFRztJQUNILHFCQUFxQixDQUFDLFNBQWlCO1FBQ3JDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNmLE9BQU87UUFDVCxDQUFDO1FBQ0QsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDdkMsTUFBTSxVQUFVLEdBQUcsYUFBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzVDLE1BQU0sbUJBQW1CLEdBQUcsU0FBUyxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM5RCxJQUFJLFNBQVMsRUFBRSxFQUFFLENBQUM7WUFDaEIsSUFBSSxZQUFvQixDQUFDO1lBQ3pCLElBQUksQ0FBQyxVQUFVLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDckUsWUFBWSxHQUFHLHdEQUF3RCxDQUFDO1lBQzFFLENBQUM7aUJBQU0sSUFBSSxTQUFTLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUNsRCxZQUFZO29CQUNWLHdGQUF3RixDQUFDO1lBQzdGLENBQUM7WUFDRCxJQUFJLFlBQVksRUFBRSxDQUFDO2dCQUNqQixNQUFNLElBQUksU0FBUyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3BDLENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxDQUFDLFVBQVUsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7WUFDeEMsU0FBUztnQkFDUCxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQztvQkFDbkUsU0FBUyxDQUFDO1FBQ2QsQ0FBQztRQUNELENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUN2QyxDQUFDLENBQUMsUUFBUSxDQUNOLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUNoQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FDM0MsVUFBVSxDQUFDLEtBQUssQ0FBQyxFQUFFO2dCQUNqQixJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7b0JBQ3ZCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUM7b0JBQ2pELElBQ0UsTUFBTSxLQUFLLFdBQVc7d0JBQ3RCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxFQUMzQyxDQUFDO3dCQUNELE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxXQUFXLENBQUMsQ0FBQztvQkFDdkQsQ0FBQztnQkFDSCxDQUFDO2dCQUNELE9BQU8sU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO1lBQ3ZELENBQUMsQ0FBQyxFQUNGLE1BQU0sQ0FBQyxhQUFhLENBQUMsRUFDckIsR0FBRyxDQUNELENBQUMsV0FBd0IsRUFBRSxFQUFFLENBQzNCLENBQUM7Z0JBQ0MsQ0FBQyxNQUFNLENBQUMsRUFBRSxXQUFXO2FBQ3RCLENBQWlCLENBQ3JCLENBQ0YsQ0FDRixDQUNGLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7WUFDM0MsQ0FBQyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsQ0FBQyxJQUFJLENBQ25DLFVBQVUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FDckUsQ0FDSjthQUNFLElBQUksQ0FDSCxTQUFTLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUN6QixRQUFRLENBQUMsR0FBRyxFQUFFO1lBQ1osSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2pDLENBQUMsQ0FBQyxDQUNIO2FBQ0EsU0FBUyxDQUFDLGtCQUFrQixDQUFDLEVBQUU7WUFDOUIsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7Z0JBQ3hCLE9BQU87WUFDVCxDQUFDO1lBQ0QsSUFBSSxDQUFDLHNCQUFzQixDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQztRQUN6RSxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFPRCxnQkFBZ0IsQ0FBQyxTQUFpQixFQUFFLE1BQWU7UUFDakQsSUFBSSxTQUFTLEVBQUUsSUFBSSx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUN2RSxNQUFNLElBQUksU0FBUyxDQUNqQiwrRUFBK0UsQ0FDaEYsQ0FBQztRQUNKLENBQUM7UUFDRCxNQUFNLE1BQU0sR0FBRyxTQUFTLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzNDLE1BQU0sbUJBQW1CLEdBQUcsU0FBUyxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM5RCxNQUFNLEdBQUcsR0FBRyxNQUFNO1lBQ2hCLENBQUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLHdCQUF3QixFQUFFLE1BQU0sQ0FBQztZQUNyRCxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQ2QsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztRQUM5QyxJQUFJLG1CQUFtQixFQUFFLENBQUM7WUFDeEIsT0FBTyxJQUFJLENBQUMsSUFBSTtpQkFDYixPQUFPLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxFQUFFLFlBQVksRUFBRSxDQUFDO2lCQUNyQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3RELENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztZQUNWLEdBQUc7WUFDSCxZQUFZO1NBQ2IsQ0FBQyxDQUFDLElBQUksQ0FDTCxHQUFHLENBQUMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsUUFBa0IsQ0FBQyxDQUFDLENBQUMsQ0FDdkUsQ0FBQztJQUNKLENBQUM7SUFFTyxlQUFlLENBQUMsTUFBYztRQUNwQyxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDcEMsQ0FBQztJQUVPLFNBQVMsQ0FDZixNQUFtQixFQUNuQixNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU07UUFFcEIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ1osT0FBTztRQUNULENBQUM7UUFDRCxJQUFJLEtBQUssR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDM0IsSUFBSSxLQUFLLElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDeEMsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNqRCxLQUFLO2dCQUNILE1BQU0sS0FBSyxXQUFXO29CQUNwQixDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQ3pCLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsTUFBTSxLQUFLLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQ2hELEVBQUUsQ0FBQyxDQUFDLENBQUM7b0JBQ1IsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM1QixDQUFDO1FBQ0QsSUFBSSxLQUFLLElBQUksSUFBSSxJQUFJLE1BQU0sS0FBSyxJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQzVELE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUM3RCxDQUFDO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRU8sZ0JBQWdCLENBQ3RCLEdBQVcsRUFDWCxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFDcEIsWUFBMEI7UUFFMUIsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQzdELElBQUksS0FBSyxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ2xCLElBQ0UsT0FBTyxLQUFLLEtBQUssUUFBUTtnQkFDekIsU0FBUyxFQUFFO2dCQUNYLE9BQU8sR0FBRyxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsV0FBVyxDQUFDLEtBQUssVUFBVSxFQUNwRCxDQUFDO2dCQUNELE9BQU8sQ0FBQyxJQUFJLENBQ1YsaUNBQWlDLE1BQU0sZ0JBQWdCLEdBQUcsNENBQTRDLENBQ3ZHLENBQUM7WUFDSixDQUFDO1lBQ0QsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdkIsQ0FBQztRQUNELElBQUksTUFBTSxLQUFLLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDM0MsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQzFCLEdBQUcsRUFDSCxJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFDM0IsWUFBWSxDQUNiLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVPLFFBQVEsQ0FDZCxHQUFXLEVBQ1gsTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQ3BCLGdCQUFnQztRQUVoQyxJQUFJLENBQUMsZ0JBQWdCLElBQUksZ0JBQWdCLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3ZELE9BQU87UUFDVCxDQUFDO1FBQ0QsS0FBSyxJQUFJLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ2pELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLEVBQUUsTUFBTSxFQUFFLGdCQUFnQixDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzFFLElBQUksS0FBSyxJQUFJLElBQUksRUFBRSxDQUFDO2dCQUNsQixPQUFPLEtBQUssQ0FBQztZQUNmLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVTLElBQUksQ0FBQyxHQUFXLEVBQUUsTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNO1FBQzlDLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQztRQUNwRSxJQUFJLEtBQUssSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUNsQixLQUFLLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQzVELENBQUM7UUFDRCxJQUFJLEtBQUssSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUNsQixPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFDRCxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFTyxZQUFZLENBQ2xCLE1BQWMsRUFDZCxXQUF3QixFQUN4QixlQUE0QixFQUM1QixPQUFpQixFQUFFO1FBRW5CLElBQUksV0FBVyxJQUFJLElBQUksSUFBSSxlQUFlLElBQUksSUFBSSxFQUFFLENBQUM7WUFDbkQsT0FBTztRQUNULENBQUM7UUFFRCxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUU7WUFDbkQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDaEUsT0FBTztZQUNULENBQUM7WUFFRCxNQUFNLFNBQVMsR0FBRyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDdkMsTUFBTSxrQkFBa0IsR0FBRyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDaEQsTUFBTSxzQkFBc0IsR0FBRyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUM7WUFFeEQsSUFBSSxrQkFBa0IsSUFBSSxzQkFBc0IsRUFBRSxDQUFDO2dCQUNqRCxJQUFJLENBQUMsWUFBWSxDQUNmLE1BQU0sRUFDTixLQUFvQixFQUNwQixTQUF3QixFQUN4QixDQUFDLEdBQUcsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUNmLENBQUM7Z0JBQ0YsT0FBTztZQUNULENBQUM7WUFFRCxJQUFJLENBQUMsa0JBQWtCLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO2dCQUNuRCxNQUFNLFVBQVUsR0FBRyxDQUFDLEdBQUcsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDL0MsSUFBSSxLQUFLLEtBQUssU0FBUyxFQUFFLENBQUM7b0JBQ3hCLE9BQU8sQ0FBQyxJQUFJLENBQ1YsNENBQTRDLE1BQU0sa0JBQWtCLFVBQVUseUZBQXlGLENBQ3hLLENBQUM7Z0JBQ0osQ0FBQztxQkFBTSxDQUFDO29CQUNOLE9BQU8sQ0FBQyxJQUFJLENBQ1YsaUNBQWlDLE1BQU0sd0JBQXdCLFVBQVUscUdBQXFHLENBQy9LLENBQUM7Z0JBQ0osQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7aUZBNVZVLGdCQUFnQiwwQ0F3QmpCLGVBQWUsZUFHZixpQkFBaUIsa0JBRUwsWUFBWTt1RUE3QnZCLGdCQUFnQixXQUFoQixnQkFBZ0IsbUJBREgsTUFBTTs7QUFhckI7SUFEUixlQUFlLEVBQUU7OEJBQ0EsVUFBVTtpREFBUztpRkFaMUIsZ0JBQWdCO2NBRDVCLFVBQVU7ZUFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUU7O3NCQXlCN0IsTUFBTTt1QkFBQyxlQUFlOztzQkFFdEIsUUFBUTs7c0JBQ1IsTUFBTTt1QkFBQyxpQkFBaUI7O3NCQUV4QixRQUFROztzQkFBSSxNQUFNO3VCQUFDLFlBQVk7cUJBakJ6QixPQUFPIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqIEBtb2R1bGUgdHJhbnNsYXRlXG4gKi9cblxuaW1wb3J0IHsgSHR0cENsaWVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7XG4gIEluamVjdCxcbiAgSW5qZWN0YWJsZSxcbiAgT25EZXN0cm95LFxuICBPcHRpb25hbCxcbiAgaXNEZXZNb2RlLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGdldCwgaGVhZCwgaXNQbGFpbk9iamVjdCwgdGVtcGxhdGUgfSBmcm9tICdsb2Rhc2gtZXMnO1xuaW1wb3J0IHtcbiAgRU1QVFksXG4gIE9ic2VydmFibGUsXG4gIFN1YmplY3QsXG4gIGZvcmtKb2luLFxuICB0aHJvd0Vycm9yLFxuICBjYXRjaEVycm9yLFxuICBmaWx0ZXIsXG4gIGZpbmFsaXplLFxuICBtYXAsXG4gIHRha2VVbnRpbCxcbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBhamF4IH0gZnJvbSAncnhqcy9hamF4JztcblxuaW1wb3J0IHsgQVBJX0dBVEVXQVksIFRFTVBMQVRFX09QVElPTlMgfSBmcm9tICcuLi9jb3JlL2NvbnN0YW50cy9jb25zdGFudHMnO1xuaW1wb3J0IHsgVE9LRU5fQkFTRV9IUkVGIH0gZnJvbSAnLi4vY29yZS9wdWJsaWMtYXBpJztcbmltcG9ydCB7IGlzQWJzb2x1dGVVcmwgfSBmcm9tICcuLi9jb3JlL3V0aWxzL2NvbW1vbic7XG5pbXBvcnQgeyBPYnNlcnZhYmxlSW5wdXQgfSBmcm9tICcuLi9jb3JlL3V0aWxzL2RlY29yYXRvcnMnO1xuaW1wb3J0IHsgcGFyc2UgfSBmcm9tICcuLi9jb3JlL3V0aWxzL3lhbWwnO1xuXG5pbXBvcnQge1xuICBGQUxMQkFDS19MQU5HVUFHRSxcbiAgTE9DQUxFX1BMQUNFSE9MREVSX1JFR0VYLFxuICBMT0NBTEVfU1RPUkFHRSxcbn0gZnJvbSAnLi9jb25zdGFudHMnO1xuaW1wb3J0IHsgVFJBTlNMQVRFX09QVElPTlMsIFRSQU5TTEFUSU9OUyB9IGZyb20gJy4vdG9rZW5zJztcbmltcG9ydCB7XG4gIFRyYW5zbGF0ZUtleSxcbiAgVHJhbnNsYXRlT3B0aW9ucyxcbiAgVHJhbnNsYXRpb24sXG4gIFRyYW5zbGF0aW9uVmFsdWUsXG4gIFRyYW5zbGF0aW9ucyxcbn0gZnJvbSAnLi90eXBlcyc7XG5cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgVHJhbnNsYXRlU2VydmljZSBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG4gIHJlYWRvbmx5IHRyYW5zbGF0aW9uc0FkZGVkJCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBkZXN0cm95JCQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gIHJlYWRvbmx5IHRyYW5zbGF0aW9uc0xpc3Q6IEFycmF5PFJlYWRvbmx5PFRyYW5zbGF0aW9ucz4+ID0gW107XG4gIHJlYWRvbmx5IHJlbW90ZVRyYW5zbGF0aW9uc0xpc3Q6IEFycmF5PFJlYWRvbmx5PFRyYW5zbGF0aW9ucz4+ID0gW107XG4gIHJlYWRvbmx5IG9wdGlvbnM6IFRyYW5zbGF0ZU9wdGlvbnM7XG5cbiAgbG9jYWxlOiBzdHJpbmc7XG5cbiAgQE9ic2VydmFibGVJbnB1dCgpXG4gIHJlYWRvbmx5IGxvY2FsZSQ6IE9ic2VydmFibGU8c3RyaW5nPjtcblxuICBnZXQgbG9jYWxlcygpIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmxvY2FsZXM7XG4gIH1cblxuICBnZXQgZmFsbGJhY2tMb2NhbGUoKSB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5mYWxsYmFja0xvY2FsZTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgaHR0cDogSHR0cENsaWVudCxcbiAgICBASW5qZWN0KFRPS0VOX0JBU0VfSFJFRilcbiAgICBwcml2YXRlIHJlYWRvbmx5IGJhc2VIcmVmOiBzdHJpbmcsXG4gICAgQE9wdGlvbmFsKClcbiAgICBASW5qZWN0KFRSQU5TTEFURV9PUFRJT05TKVxuICAgIG9wdGlvbnM6IFRyYW5zbGF0ZU9wdGlvbnMsXG4gICAgQE9wdGlvbmFsKCkgQEluamVjdChUUkFOU0xBVElPTlMpIHRyYW5zbGF0aW9uTGlzdDogVHJhbnNsYXRpb25zW10sXG4gICkge1xuICAgIHRoaXMubG9jYWxlID0gb3B0aW9ucz8ubG9jYWxlIHx8IG5hdmlnYXRvci5sYW5ndWFnZTtcbiAgICB0aGlzLm9wdGlvbnMgPSB7XG4gICAgICBsb2NhbGVzOiBbdGhpcy5sb2NhbGVdLFxuICAgICAgZmFsbGJhY2tMb2NhbGU6IEZBTExCQUNLX0xBTkdVQUdFLFxuICAgICAgLi4ub3B0aW9ucyxcbiAgICB9O1xuXG4gICAgdGhpcy50cmFuc2xhdGlvbnNMaXN0ID0gW1xuICAgICAgb3B0aW9ucz8udHJhbnNsYXRpb25zLFxuICAgICAgLi4uKHRyYW5zbGF0aW9uTGlzdCB8fCBbXSksXG4gICAgXS5maWx0ZXIoQm9vbGVhbik7XG5cbiAgICBpZiAob3B0aW9ucz8ucmVtb3RlVXJsKSB7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShvcHRpb25zLnJlbW90ZVVybCkpIHtcbiAgICAgICAgb3B0aW9ucy5yZW1vdGVVcmwuZm9yRWFjaCh1cmwgPT4gdGhpcy5hZGRSZW1vdGVUcmFuc2xhdGlvbnModXJsKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmFkZFJlbW90ZVRyYW5zbGF0aW9ucyhvcHRpb25zLnJlbW90ZVVybCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5kZXN0cm95JCQubmV4dCgpO1xuICAgIHRoaXMuZGVzdHJveSQkLmNvbXBsZXRlKCk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIGtleSAtIOe/u+ivkWtleVxuICAgKiBAcGFyYW0gZGF0YSAtIOagueaNrue/u+ivkeS4iuS4i+aWh+aVsOaNruiOt+WPlue/u+ivkeWGheWuue+8jOe/u+ivkemhueS4jeWtmOWcqOebtOaOpei/lOWbniBrZXkg5paH5pysXG4gICAqIEBwYXJhbSBpZ25vcmVOb25FeGlzdCAtIOW8gOWPkeeOr+Wig+aYr+WQpuW/veinhuS4jeWtmOWcqOeahOe/u+ivkemhuVxuICAgKi9cbiAgZ2V0KGtleTogVHJhbnNsYXRlS2V5LCBkYXRhPzogdW5rbm93bikge1xuICAgIGNvbnN0IHRyYW5zbGF0aW9uID0gdGhpcy5nZXRSYXcoa2V5KTtcbiAgICBpZiAoZGF0YSAhPSBudWxsICYmIHR5cGVvZiBkYXRhICE9PSAnb2JqZWN0Jykge1xuICAgICAgZGF0YSA9IFtkYXRhXTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB0ZW1wbGF0ZSh0cmFuc2xhdGlvbiwgVEVNUExBVEVfT1BUSU9OUykoZGF0YSBhcyBvYmplY3QpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGVbaXNEZXZNb2RlKCkgPyAnZXJyb3InIDogJ3dhcm4nXShcbiAgICAgICAgYFRoZSB0cmFuc2xhdGlvbiBrZXkgJyR7a2V5fScgaXMgbWlzc2luZyB0aGUgbmVjZXNzYXJ5IHBhcmFtZXRlcnMuYCxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIOebtOaOpei/lOWbnue/u+ivkeaWh+acrOaooeadv1xuICAgKiBAcGFyYW0ga2V5IC0g57+76K+Ra2V5XG4gICAqIEBwYXJhbSBpZ25vcmVOb25FeGlzdCAtIOW8gOWPkeeOr+Wig+aYr+WQpuW/veinhuS4jeWtmOWcqOeahOe/u+ivkemhuVxuICAgKi9cbiAgZ2V0UmF3KGtleTogVHJhbnNsYXRlS2V5KSB7XG4gICAgcmV0dXJuIHR5cGVvZiBrZXkgPT09ICdzdHJpbmcnXG4gICAgICA/IHRoaXMuX2dldChrZXkpXG4gICAgICA6ICh0aGlzLl9nZXRWYWx1ZShrZXkpIGFzIHN0cmluZyk7XG4gIH1cblxuICAvKipcbiAgICog5qC55o2uIGBsb2NhbGVzYCDlvqrnjq/liIfmjaLlvZPliY3ljLrln5/orr7nva5cbiAgICovXG4gIHRvZ2dsZUxvY2FsZSgpIHtcbiAgICBjb25zdCBpbmRleCA9IHRoaXMub3B0aW9ucy5sb2NhbGVzLmluZGV4T2YodGhpcy5sb2NhbGUpO1xuICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgIGlmIChpc0Rldk1vZGUoKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdgbG9jYWxlc2AgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkIGNvcnJlY3RseScpO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBuZXh0TG9jYWxlID1cbiAgICAgIHRoaXMub3B0aW9ucy5sb2NhbGVzW1xuICAgICAgICBpbmRleCA9PT0gdGhpcy5vcHRpb25zLmxvY2FsZXMubGVuZ3RoIC0gMSA/IDAgOiBpbmRleCArIDFcbiAgICAgIF07XG5cbiAgICBpZiAoIW5leHRMb2NhbGUgfHwgdGhpcy5sb2NhbGUgPT09IG5leHRMb2NhbGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnNldExvY2FsZShuZXh0TG9jYWxlKTtcbiAgfVxuXG4gIHNldExvY2FsZShsb2NhbGU6IHN0cmluZykge1xuICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKExPQ0FMRV9TVE9SQUdFLCBsb2NhbGUpO1xuICAgIHRoaXMubG9jYWxlID0gbG9jYWxlO1xuICB9XG5cbiAgLyoqXG4gICAqIOaJi+WKqOa3u+WKoOivreiogOWMhVxuICAgKi9cbiAgYWRkVHJhbnNsYXRpb25zKHRyYW5zbGF0aW9uczogVHJhbnNsYXRpb25zKSB7XG4gICAgdGhpcy50cmFuc2xhdGlvbnNMaXN0LnVuc2hpZnQoT2JqZWN0LmZyZWV6ZSh0cmFuc2xhdGlvbnMpKTtcbiAgICB0aGlzLnRyYW5zbGF0aW9uc0FkZGVkJC5uZXh0KCk7XG4gIH1cblxuICAvKipcbiAgICog5omL5Yqo5re75Yqg6K+t6KiA5YyFXG4gICAqL1xuICBhZGRSZW1vdGVUcmFuc2xhdGlvbnMocmVtb3RlVXJsOiBzdHJpbmcpIHtcbiAgICBpZiAoIXJlbW90ZVVybCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICByZW1vdGVVcmwgPSBoZWFkKHJlbW90ZVVybC5zcGxpdCgvIy8pKTtcbiAgICBjb25zdCBpc0Fic29sdXRlID0gaXNBYnNvbHV0ZVVybChyZW1vdGVVcmwpO1xuICAgIGNvbnN0IGlzQXBpR2F0ZVdheVJlcXVlc3QgPSByZW1vdGVVcmwuc3RhcnRzV2l0aChBUElfR0FURVdBWSk7XG4gICAgaWYgKGlzRGV2TW9kZSgpKSB7XG4gICAgICBsZXQgZXJyb3JNZXNzYWdlOiBzdHJpbmc7XG4gICAgICBpZiAoIWlzQWJzb2x1dGUgJiYgKCF0aGlzLmJhc2VIcmVmIHx8ICFpc0Fic29sdXRlVXJsKHRoaXMuYmFzZUhyZWYpKSkge1xuICAgICAgICBlcnJvck1lc3NhZ2UgPSAnYWJzb2x1dGUgYmFzZSBocmVmIGlzIHJlcXVpcmVkIGZvciByZWxhdGl2ZSByZW1vdGUgdXJsJztcbiAgICAgIH0gZWxzZSBpZiAocmVtb3RlVXJsLnNwbGl0KCc/JylbMF0uaW5jbHVkZXMoJy4vJykpIHtcbiAgICAgICAgZXJyb3JNZXNzYWdlID1cbiAgICAgICAgICAnZG8gbm90IHVzZSBhbnkgZG90IHdpdGggc2xhc2ggZm9yIHJlbGF0aXZlIHVybCB3aGljaCBzaG91bGQgYWx3YXlzIGJhc2UgZnJvbSBiYXNlIGhyZWYnO1xuICAgICAgfVxuICAgICAgaWYgKGVycm9yTWVzc2FnZSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGVycm9yTWVzc2FnZSk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmICghaXNBYnNvbHV0ZSAmJiAhaXNBcGlHYXRlV2F5UmVxdWVzdCkge1xuICAgICAgcmVtb3RlVXJsID1cbiAgICAgICAgKHRoaXMuYmFzZUhyZWYuZW5kc1dpdGgoJy8nKSA/IHRoaXMuYmFzZUhyZWYgOiB0aGlzLmJhc2VIcmVmICsgJy8nKSArXG4gICAgICAgIHJlbW90ZVVybDtcbiAgICB9XG4gICAgKExPQ0FMRV9QTEFDRUhPTERFUl9SRUdFWC50ZXN0KHJlbW90ZVVybClcbiAgICAgID8gZm9ya0pvaW4oXG4gICAgICAgICAgdGhpcy5vcHRpb25zLmxvY2FsZXMubWFwKGxvY2FsZSA9PlxuICAgICAgICAgICAgdGhpcy5mZXRjaFRyYW5zbGF0aW9uKHJlbW90ZVVybCwgbG9jYWxlKS5waXBlKFxuICAgICAgICAgICAgICBjYXRjaEVycm9yKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLmxvb3NlKSB7XG4gICAgICAgICAgICAgICAgICBjb25zdCBsb29zZUxvY2FsZSA9IHRoaXMuX2dldExvb3NlTG9jYWxlKGxvY2FsZSk7XG4gICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgIGxvY2FsZSAhPT0gbG9vc2VMb2NhbGUgJiZcbiAgICAgICAgICAgICAgICAgICAgIXRoaXMub3B0aW9ucy5sb2NhbGVzLmluY2x1ZGVzKGxvb3NlTG9jYWxlKVxuICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmZldGNoVHJhbnNsYXRpb24ocmVtb3RlVXJsLCBsb29zZUxvY2FsZSk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBpc0Rldk1vZGUoKSA/IHRocm93RXJyb3IoKCkgPT4gZXJyb3IpIDogRU1QVFk7XG4gICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICBmaWx0ZXIoaXNQbGFpbk9iamVjdCksXG4gICAgICAgICAgICAgIG1hcChcbiAgICAgICAgICAgICAgICAodHJhbnNsYXRpb246IFRyYW5zbGF0aW9uKSA9PlxuICAgICAgICAgICAgICAgICAgKHtcbiAgICAgICAgICAgICAgICAgICAgW2xvY2FsZV06IHRyYW5zbGF0aW9uLFxuICAgICAgICAgICAgICAgICAgfSkgYXMgVHJhbnNsYXRpb25zLFxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICApLFxuICAgICAgICApLnBpcGUobWFwKF8gPT4gXy5yZWR1Y2UoT2JqZWN0LmFzc2lnbikpKVxuICAgICAgOiB0aGlzLmZldGNoVHJhbnNsYXRpb24ocmVtb3RlVXJsKS5waXBlKFxuICAgICAgICAgIGNhdGNoRXJyb3IoZXJyb3IgPT4gKGlzRGV2TW9kZSgpID8gdGhyb3dFcnJvcigoKSA9PiBlcnJvcikgOiBFTVBUWSkpLFxuICAgICAgICApXG4gICAgKVxuICAgICAgLnBpcGUoXG4gICAgICAgIHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkJCksXG4gICAgICAgIGZpbmFsaXplKCgpID0+IHtcbiAgICAgICAgICB0aGlzLnRyYW5zbGF0aW9uc0FkZGVkJC5uZXh0KCk7XG4gICAgICAgIH0pLFxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZShyZW1vdGVUcmFuc2xhdGlvbnMgPT4ge1xuICAgICAgICBpZiAoIXJlbW90ZVRyYW5zbGF0aW9ucykge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbW90ZVRyYW5zbGF0aW9uc0xpc3QudW5zaGlmdChPYmplY3QuZnJlZXplKHJlbW90ZVRyYW5zbGF0aW9ucykpO1xuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICog5LuO6L+c56iLIHVybCDmqKHmnb/lkozljLrln5/ojrflj5bnv7vor5HljIVcbiAgICovXG4gIGZldGNoVHJhbnNsYXRpb24ocmVtb3RlVXJsOiBzdHJpbmcpOiBPYnNlcnZhYmxlPFRyYW5zbGF0aW9ucz47XG4gIGZldGNoVHJhbnNsYXRpb24ocmVtb3RlVXJsOiBzdHJpbmcsIGxvY2FsZTogc3RyaW5nKTogT2JzZXJ2YWJsZTxUcmFuc2xhdGlvbj47XG4gIGZldGNoVHJhbnNsYXRpb24ocmVtb3RlVXJsOiBzdHJpbmcsIGxvY2FsZT86IHN0cmluZykge1xuICAgIGlmIChpc0Rldk1vZGUoKSAmJiBMT0NBTEVfUExBQ0VIT0xERVJfUkVHRVgudGVzdChyZW1vdGVVcmwpICYmICFsb2NhbGUpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICdgbG9jYWxlYCBpcyByZXF1aXJlZCBzaW5lIHRoZSBwcm92aWRlZCByZW1vdGUgdXJsIGNvbnRhaW5zIGxvY2FsZSBwbGFjZWhvbGRlcicsXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBpc0pTT04gPSByZW1vdGVVcmwuZW5kc1dpdGgoJy5qc29uJyk7XG4gICAgY29uc3QgaXNBcGlHYXRlV2F5UmVxdWVzdCA9IHJlbW90ZVVybC5zdGFydHNXaXRoKEFQSV9HQVRFV0FZKTtcbiAgICBjb25zdCB1cmwgPSBsb2NhbGVcbiAgICAgID8gcmVtb3RlVXJsLnJlcGxhY2UoTE9DQUxFX1BMQUNFSE9MREVSX1JFR0VYLCBsb2NhbGUpXG4gICAgICA6IHJlbW90ZVVybDtcbiAgICBjb25zdCByZXNwb25zZVR5cGUgPSBpc0pTT04gPyAnanNvbicgOiAndGV4dCc7XG4gICAgaWYgKGlzQXBpR2F0ZVdheVJlcXVlc3QpIHtcbiAgICAgIHJldHVybiB0aGlzLmh0dHBcbiAgICAgICAgLnJlcXVlc3QoJ0dFVCcsIHVybCwgeyByZXNwb25zZVR5cGUgfSlcbiAgICAgICAgLnBpcGUobWFwKGJvZHkgPT4gKGlzSlNPTiA/IGJvZHkgOiBwYXJzZShib2R5KSkpKTtcbiAgICB9XG4gICAgcmV0dXJuIGFqYXgoe1xuICAgICAgdXJsLFxuICAgICAgcmVzcG9uc2VUeXBlLFxuICAgIH0pLnBpcGUoXG4gICAgICBtYXAoKHsgcmVzcG9uc2UgfSkgPT4gKGlzSlNPTiA/IHJlc3BvbnNlIDogcGFyc2UocmVzcG9uc2UgYXMgc3RyaW5nKSkpLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIF9nZXRMb29zZUxvY2FsZShsb2NhbGU6IHN0cmluZykge1xuICAgIHJldHVybiBoZWFkKGxvY2FsZS5zcGxpdCgvW18tXS8pKTtcbiAgfVxuXG4gIHByaXZhdGUgX2dldFZhbHVlKFxuICAgIHNvdXJjZTogVHJhbnNsYXRpb24sXG4gICAgbG9jYWxlID0gdGhpcy5sb2NhbGUsXG4gICk6IFRyYW5zbGF0aW9uVmFsdWUge1xuICAgIGlmICghc291cmNlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCB2YWx1ZSA9IHNvdXJjZVtsb2NhbGVdO1xuICAgIGlmICh2YWx1ZSA9PSBudWxsICYmIHRoaXMub3B0aW9ucy5sb29zZSkge1xuICAgICAgY29uc3QgbG9vc2VMb2NhbGUgPSB0aGlzLl9nZXRMb29zZUxvY2FsZShsb2NhbGUpO1xuICAgICAgdmFsdWUgPVxuICAgICAgICBsb2NhbGUgPT09IGxvb3NlTG9jYWxlXG4gICAgICAgICAgPyBPYmplY3QuZW50cmllcyhzb3VyY2UpLmZpbmQoXG4gICAgICAgICAgICAgIChba2V5XSkgPT4gbG9jYWxlID09PSB0aGlzLl9nZXRMb29zZUxvY2FsZShrZXkpLFxuICAgICAgICAgICAgKT8uWzFdXG4gICAgICAgICAgOiBzb3VyY2VbbG9vc2VMb2NhbGVdO1xuICAgIH1cbiAgICBpZiAodmFsdWUgPT0gbnVsbCAmJiBsb2NhbGUgIT09IHRoaXMub3B0aW9ucy5mYWxsYmFja0xvY2FsZSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2dldFZhbHVlKHNvdXJjZSwgdGhpcy5vcHRpb25zLmZhbGxiYWNrTG9jYWxlKTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0V2l0aEZhbGxiYWNrKFxuICAgIGtleTogc3RyaW5nLFxuICAgIGxvY2FsZSA9IHRoaXMubG9jYWxlLFxuICAgIHRyYW5zbGF0aW9uczogVHJhbnNsYXRpb25zLFxuICApOiBzdHJpbmcge1xuICAgIGNvbnN0IHZhbHVlID0gZ2V0KHRoaXMuX2dldFZhbHVlKHRyYW5zbGF0aW9ucywgbG9jYWxlKSwga2V5KTtcbiAgICBpZiAodmFsdWUgIT0gbnVsbCkge1xuICAgICAgaWYgKFxuICAgICAgICB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmXG4gICAgICAgIGlzRGV2TW9kZSgpICYmXG4gICAgICAgIHR5cGVvZiBnZXQodmFsdWUsIFN5bWJvbC50b1ByaW1pdGl2ZSkgIT09ICdmdW5jdGlvbidcbiAgICAgICkge1xuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgYFRoZSB0cmFuc2xhdGlvbiBmb3IgbG9jYWxlOiBcXGAke2xvY2FsZX1cXGAgYW5kIGtleTpcXGAke2tleX1cXGAgaXMgYW4gb2JqZWN0LCB3aGljaCBjb3VsZCBiZSB1bmV4cGVjdGVkYCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBTdHJpbmcodmFsdWUpO1xuICAgIH1cbiAgICBpZiAobG9jYWxlICE9PSB0aGlzLm9wdGlvbnMuZmFsbGJhY2tMb2NhbGUpIHtcbiAgICAgIHJldHVybiB0aGlzLl9nZXRXaXRoRmFsbGJhY2soXG4gICAgICAgIGtleSxcbiAgICAgICAgdGhpcy5vcHRpb25zLmZhbGxiYWNrTG9jYWxlLFxuICAgICAgICB0cmFuc2xhdGlvbnMsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2dldEJhc2UoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgbG9jYWxlID0gdGhpcy5sb2NhbGUsXG4gICAgdHJhbnNsYXRpb25zTGlzdDogVHJhbnNsYXRpb25zW10sXG4gICkge1xuICAgIGlmICghdHJhbnNsYXRpb25zTGlzdCB8fCB0cmFuc2xhdGlvbnNMaXN0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBmb3IgKGxldCBpID0gdHJhbnNsYXRpb25zTGlzdC5sZW5ndGg7IGkgPiAwOyBpLS0pIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5fZ2V0V2l0aEZhbGxiYWNrKGtleSwgbG9jYWxlLCB0cmFuc2xhdGlvbnNMaXN0W2kgLSAxXSk7XG4gICAgICBpZiAodmFsdWUgIT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIF9nZXQoa2V5OiBzdHJpbmcsIGxvY2FsZSA9IHRoaXMubG9jYWxlKSB7XG4gICAgbGV0IHZhbHVlID0gdGhpcy5fZ2V0QmFzZShrZXksIGxvY2FsZSwgdGhpcy5yZW1vdGVUcmFuc2xhdGlvbnNMaXN0KTtcbiAgICBpZiAodmFsdWUgPT0gbnVsbCkge1xuICAgICAgdmFsdWUgPSB0aGlzLl9nZXRCYXNlKGtleSwgbG9jYWxlLCB0aGlzLnRyYW5zbGF0aW9uc0xpc3QpO1xuICAgIH1cbiAgICBpZiAodmFsdWUgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4ga2V5O1xuICB9XG5cbiAgcHJpdmF0ZSBfY29tcGFyZUtleXMoXG4gICAgbG9jYWxlOiBzdHJpbmcsXG4gICAgdHJhbnNsYXRpb246IFRyYW5zbGF0aW9uLFxuICAgIHByZXZUcmFuc2xhdGlvbjogVHJhbnNsYXRpb24sXG4gICAgcGF0aDogc3RyaW5nW10gPSBbXSxcbiAgKSB7XG4gICAgaWYgKHRyYW5zbGF0aW9uID09IG51bGwgfHwgcHJldlRyYW5zbGF0aW9uID09IG51bGwpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBPYmplY3QuZW50cmllcyh0cmFuc2xhdGlvbikuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChwcmV2VHJhbnNsYXRpb24sIGtleSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwcmV2VmFsdWUgPSBwcmV2VHJhbnNsYXRpb25ba2V5XTtcbiAgICAgIGNvbnN0IHZhbHVlSXNQbGFpbk9iamVjdCA9IGlzUGxhaW5PYmplY3QodmFsdWUpO1xuICAgICAgY29uc3QgcHJldlZhbHVlSXNQbGFpbk9iamVjdCA9IGlzUGxhaW5PYmplY3QocHJldlZhbHVlKTtcblxuICAgICAgaWYgKHZhbHVlSXNQbGFpbk9iamVjdCAmJiBwcmV2VmFsdWVJc1BsYWluT2JqZWN0KSB7XG4gICAgICAgIHRoaXMuX2NvbXBhcmVLZXlzKFxuICAgICAgICAgIGxvY2FsZSxcbiAgICAgICAgICB2YWx1ZSBhcyBUcmFuc2xhdGlvbixcbiAgICAgICAgICBwcmV2VmFsdWUgYXMgVHJhbnNsYXRpb24sXG4gICAgICAgICAgWy4uLnBhdGgsIGtleV0sXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKCF2YWx1ZUlzUGxhaW5PYmplY3QgJiYgIXByZXZWYWx1ZUlzUGxhaW5PYmplY3QpIHtcbiAgICAgICAgY29uc3Qgb3V0cHV0UGF0aCA9IFsuLi5wYXRoLCBrZXldLmpvaW4oJyAtPiAnKTtcbiAgICAgICAgaWYgKHZhbHVlID09PSBwcmV2VmFsdWUpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICBgVGhlIGN1c3RvbWl6ZWQgdHJhbnNsYXRpb24gZm9yIGxvY2FsZTogXFxgJHtsb2NhbGV9XFxgIGFuZCBwYXRoOiBcXGAke291dHB1dFBhdGh9XFxgIGlzIGR1cGxpY2F0ZWQgd2l0aCB0aGUgb3RoZXIgdHJhbnNsYXRpb24sIHBsZWFzZSByZW1vdmUgaXQgaW4geW91ciB0cmFuc2xhdGlvbiBmaWxlLmAsXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICBgVHdvIGtleXMgdGhhdCB0aGUgbG9jYWxlIGlzIFxcYCR7bG9jYWxlfVxcYCBhbmQgdGhlIHBhdGggaXMgXFxgJHtvdXRwdXRQYXRofVxcYCBhcmUgc2FtZSwgIGJ1dCB0aGVpciB2YWx1ZXMgYXJlIG5vdCBlcXVhbCAsIHBsZWFzZSByZW1vdmUgb25lIG9mIHRoZW0gb3IgY2hhbmdlIG9uZSBvZiB0aGUga2V5cy5gLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuIl19
869
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNsYXRlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWJzL2NvbW1vbi9zcmMvdHJhbnNsYXRlL3RyYW5zbGF0ZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O0dBR0c7QUFFSCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbEQsT0FBTyxFQUNMLE1BQU0sRUFDTixVQUFVLEVBRVYsUUFBUSxFQUNSLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDckQsT0FBTyxFQUNMLFVBQVUsRUFDVixPQUFPLEVBQ1AsUUFBUSxFQUNSLFVBQVUsRUFDVixLQUFLLEVBQ0wsVUFBVSxFQUNWLE1BQU0sRUFDTixRQUFRLEVBQ1IsR0FBRyxFQUNILFNBQVMsR0FDVixNQUFNLE1BQU0sQ0FBQztBQUNkLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFakMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzFELE9BQU8sRUFBRSxlQUFlLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDdEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUUzQyxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLHdCQUF3QixFQUN4QixjQUFjLEdBQ2YsTUFBTSxhQUFhLENBQUM7QUFDckIsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNoRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsWUFBWSxFQUFFLE1BQU0sVUFBVSxD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IjpbIi8qKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKiBAbW9kdWxlIHRyYW5zbGF0ZVxuICovXG5cbmltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQge1xuICBJbmplY3QsXG4gIEluamVjdGFibGUsXG4gIE9uRGVzdHJveSxcbiAgT3B0aW9uYWwsXG4gIGlzRGV2TW9kZSxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBJbnRsTWVzc2FnZUZvcm1hdCB9IGZyb20gJ2ludGwtbWVzc2FnZWZvcm1hdCc7XG5pbXBvcnQgeyBnZXQsIGhlYWQsIGlzUGxhaW5PYmplY3QgfSBmcm9tICdsb2Rhc2gtZXMnO1xuaW1wb3J0IHtcbiAgT2JzZXJ2YWJsZSxcbiAgU3ViamVjdCxcbiAgZm9ya0pvaW4sXG4gIHRocm93RXJyb3IsXG4gIEVNUFRZLFxuICBjYXRjaEVycm9yLFxuICBmaWx0ZXIsXG4gIGZpbmFsaXplLFxuICBtYXAsXG4gIHRha2VVbnRpbCxcbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBhamF4IH0gZnJvbSAncnhqcy9hamF4JztcblxuaW1wb3J0IHsgQVBJX0dBVEVXQVkgfSBmcm9tICcuLi9jb3JlL2NvbnN0YW50cy9jb25zdGFudHMnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZUlucHV0LCBUT0tFTl9CQVNFX0hSRUYgfSBmcm9tICcuLi9jb3JlL3B1YmxpYy1hcGknO1xuaW1wb3J0IHsgaXNBYnNvbHV0ZVVybCB9IGZyb20gJy4uL2NvcmUvdXRpbHMvY29tbW9uJztcbmltcG9ydCB7IHBhcnNlIH0gZnJvbSAnLi4vY29yZS91dGlscy95YW1sJztcblxuaW1wb3J0IHtcbiAgRkFMTEJBQ0tfTEFOR1VBR0UsXG4gIExPQ0FMRV9QTEFDRUhPTERFUl9SRUdFWCxcbiAgTE9DQUxFX1NUT1JBR0UsXG59IGZyb20gJy4vY29uc3RhbnRzJztcbmltcG9ydCB7IGdldFVzZXJMYW5ndWFnZSB9IGZyb20gJy4vaTE4bi1jb25maWcnO1xuaW1wb3J0IHsgVFJBTlNMQVRFX09QVElPTlMsIFRSQU5TTEFUSU9OUyB9IGZyb20gJy4vdG9rZW5zJztcbmltcG9ydCB7XG4gIFRyYW5zbGF0ZUtleSxcbiAgVHJhbnNsYXRlT3B0aW9ucyxcbiAgVHJhbnNsYXRpb24sXG4gIFRyYW5zbGF0aW9uVmFsdWUsXG4gIFRyYW5zbGF0aW9ucyxcbiAgVGVtcGxhdGVEYXRhLFxuICBJY3VEYXRhLFxufSBmcm9tICcuL3R5cGVzJztcblxuLyoqXG4gKiDlm73pmYXljJbnv7vor5HmnI3liqFcbiAqXG4gKiDnibnmgKfvvJpcbiAqIC0g5pSv5oyB5aSa5bGC57qn57+76K+R5LyY5YWI57qn77yI6L+c56iL57+76K+RID4g5omL5Yqo5re75Yqg57+76K+RID4g6YWN572u57+76K+R77yJXG4gKiAtIOaUr+aMgeWKqOaAgeivreiogOWIh+aNolxuICogLSDmlK/mjIEgSUNVIE1lc3NhZ2UgRm9ybWF0IOaooeadv+aPkuWAvFxuICogLSDmlK/mjIHlrr3mnb7mqKHlvI/or63oqIDljLnphY1cbiAqIC0g5pSv5oyB5byC5q2l6L+c56iL57+76K+R5Yqg6L29XG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgVHJhbnNsYXRlU2VydmljZSBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG4gIC8qKiDnv7vor5Hmt7vliqDpgJrnn6XmtYEgKi9cbiAgcHJpdmF0ZSByZWFkb25seSB0cmFuc2xhdGlvbnNBZGRlZCQkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICByZWFkb25seSB0cmFuc2xhdGlvbnNBZGRlZCQgPSB0aGlzLnRyYW5zbGF0aW9uc0FkZGVkJCQuYXNPYnNlcnZhYmxlKCk7XG5cbiAgLyoqIOe7hOS7tumUgOavgemAmuefpea1gSAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3kkJCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgLyoqIOacrOWcsOe/u+ivkeWIl+ihqO+8iOS8mOWFiOe6p++8muWQjuWKoOWFpeeahOS8mOWFiOe6p+abtOmrmO+8iSAqL1xuICByZWFkb25seSB0cmFuc2xhdGlvbnNMaXN0OiBBcnJheTxSZWFkb25seTxUcmFuc2xhdGlvbnM+PiA9IFtdO1xuXG4gIC8qKiDov5znqIvnv7vor5HliJfooajvvIjkvJjlhYjnuqfmnIDpq5jvvIkgKi9cbiAgcmVhZG9ubHkgcmVtb3RlVHJhbnNsYXRpb25zTGlzdDogQXJyYXk8UmVhZG9ubHk8VHJhbnNsYXRpb25zPj4gPSBbXTtcblxuICAvKiog57+76K+R6YWN572u6YCJ6aG5ICovXG4gIHJlYWRvbmx5IG9wdGlvbnM6IFRyYW5zbGF0ZU9wdGlvbnM7XG5cbiAgLyoqIOW9k+WJjeivreiogOeOr+WigyAqL1xuICBsb2NhbGU6IHN0cmluZztcblxuICAvKiog5b2T5YmN6K+t6KiA546v5aKD77yI5ZON5bqU5byP77yJICovXG4gIEBPYnNlcnZhYmxlSW5wdXQoKVxuICByZWFkb25seSBsb2NhbGUkOiBPYnNlcnZhYmxlPHN0cmluZz47XG5cbiAgLyoqIOiOt+WPluaUr+aMgeeahOivreiogOWIl+ihqCAqL1xuICBnZXQgbG9jYWxlcygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5sb2NhbGVzO1xuICB9XG5cbiAgLyoqIOiOt+WPluWbnumAgOivreiogCAqL1xuICBnZXQgZmFsbGJhY2tMb2NhbGUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmZhbGxiYWNrTG9jYWxlO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBodHRwOiBIdHRwQ2xpZW50LFxuICAgIEBJbmplY3QoVE9LRU5fQkFTRV9IUkVGKSBwcml2YXRlIHJlYWRvbmx5IGJhc2VIcmVmOiBzdHJpbmcsXG4gICAgQE9wdGlvbmFsKCkgQEluamVjdChUUkFOU0xBVEVfT1BUSU9OUykgb3B0aW9uczogVHJhbnNsYXRlT3B0aW9ucyxcbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KFRSQU5TTEFUSU9OUykgdHJhbnNsYXRpb25MaXN0OiBUcmFuc2xhdGlvbnNbXSxcbiAgKSB7XG4gICAgLy8g5Yid5aeL5YyW6K+t6KiA546v5aKDXG4gICAgdGhpcy5sb2NhbGUgPSB0aGlzLmdldEluaXRpYWxMb2NhbGUob3B0aW9ucyk7XG5cbiAgICAvLyDliJ3lp4vljJbphY3nva7pgInpoblcbiAgICB0aGlzLm9wdGlvbnMgPSB7XG4gICAgICBsb2NhbGVzOiBbdGhpcy5sb2NhbGVdLFxuICAgICAgZmFsbGJhY2tMb2NhbGU6IEZBTExCQUNLX0xBTkdVQUdFLFxuICAgICAgbG9vc2U6IGZhbHNlLFxuICAgICAgLi4ub3B0aW9ucyxcbiAgICB9O1xuXG4gICAgLy8g5Yid5aeL5YyW57+76K+R5YiX6KGoXG4gICAgdGhpcy50cmFuc2xhdGlvbnNMaXN0ID0gdGhpcy5nZXRJbml0aWFsaXplVHJhbnNsYXRpb25zKFxuICAgICAgb3B0aW9ucyxcbiAgICAgIHRyYW5zbGF0aW9uTGlzdCxcbiAgICApO1xuXG4gICAgLy8g5Yqg6L296L+c56iL57+76K+RXG4gICAgdGhpcy5sb2FkUmVtb3RlVHJhbnNsYXRpb25zKG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIOe7hOS7tumUgOavgea4heeQhlxuICAgKi9cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5kZXN0cm95JCQubmV4dCgpO1xuICAgIHRoaXMuZGVzdHJveSQkLmNvbXBsZXRlKCk7XG4gIH1cblxuICAvKipcbiAgICog6I635Y+W57+76K+R5paH5pys5bm26L+b6KGM5qih5p2/5o+S5YC8XG4gICAqIOiHquWKqOWwhuS8oOe7nyB7eyBrZXkgfX0g6K+t5rOV6L2s5o2i5Li6IElDVSB7a2V5fSDmoLzlvI/ov5vooYzop6PmnpBcbiAgICog5ZCM5pe25pSv5oyB5Y6f55SfIElDVSBNZXNzYWdlIEZvcm1hdCDor63ms5VcbiAgICogQHBhcmFtIGtleSAtIOe/u+ivkemUruaIlue/u+ivkeWvueixoVxuICAgKiBAcGFyYW0gZGF0YSAtIOaooeadv+aVsOaNru+8iOaUr+aMgeWfuuacrOexu+Wei+OAgURhdGXjgIHlr7nosaHlkozmlbDnu4TvvIlcbiAgICogQHJldHVybnMg57+76K+R5ZCO55qE5paH5pysXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogLy8g5a+56LGh5Y+C5pWw77yI5o6o6I2Q77yJXG4gICAqIHRyYW5zbGF0ZS5nZXQoJ2hlbGxvJywgeyBuYW1lOiAnV29ybGQnIH0pIC8vIOaooeadvzogXCJIZWxsbyB7bmFtZX1cIlxuICAgKlxuICAgKiAvLyDln7rmnKznsbvlnovlj4LmlbDvvIjoh6rliqjovazmjaLkuLoge3ZhbHVlfe+8iVxuICAgKiB0cmFuc2xhdGUuZ2V0KCd3ZWxjb21lJywgJ0pvaG4nKSAvLyDmqKHmnb86IFwiV2VsY29tZSB7dmFsdWV9XCJcbiAgICpcbiAgICogLy8gSUNVIOagvOW8j++8iOaVsOWtl++8iVxuICAgKiB0cmFuc2xhdGUuZ2V0KCdpdGVtQ291bnQnLCB7IGNvdW50OiA1IH0pXG4gICAqXG4gICAqIC8vIElDVSDmoLzlvI/vvIjml6XmnJ/vvIzpu5jorqTmnKzlnLDljJbvvIlcbiAgICogdHJhbnNsYXRlLmdldCgnY3JlYXRlZEF0JywgeyBkYXRlOiBuZXcgRGF0ZSgpIH0pXG4gICAqIGBgYFxuICAgKi9cbiAgZ2V0KGtleTogVHJhbnNsYXRlS2V5LCBkYXRhPzogVGVtcGxhdGVEYXRhKTogc3RyaW5nIHtcbiAgICBjb25zdCB0cmFuc2xhdGlvbiA9IHRoaXMuZ2V0UmF3KGtleSk7XG5cbiAgICBpZiAoZGF0YSA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJhbnNsYXRpb247XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIC8vIOWwhuS8oOe7n+eahCB7eyBrZXkgfX0g6K+t5rOV6L2s5o2i5Li6IElDVSB7a2V5fSDmoLzlvI9cbiAgICAgIGNvbnN0IGljdU1lc3NhZ2UgPSB0aGlzLmNvbnZlcnRUb0ljdUZvcm1hdCh0cmFuc2xhdGlvbik7XG4gICAgICAvLyDlsIbmlbDmja7ovazmjaLkuLogSUNVIOWFvOWuueeahOagvOW8j1xuICAgICAgY29uc3QgaWN1RGF0YSA9IHRoaXMubm9ybWFsaXplQW5kQ29udmVydFRvSWN1RGF0YShkYXRhKTtcbiAgICAgIHJldHVybiB0aGlzLmZvcm1hdEljdU1lc3NhZ2UoaWN1TWVzc2FnZSwgaWN1RGF0YSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMuaGFuZGxlVGVtcGxhdGVFcnJvcihrZXksIGVycm9yKTtcbiAgICAgIHJldHVybiB0cmFuc2xhdGlvbjtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICog6I635Y+W5Y6f5aeL57+76K+R5paH5pys5qih5p2/77yI5LiN6L+b6KGM5o+S5YC85aSE55CG77yJXG4gICAqIEBwYXJhbSBrZXkgLSDnv7vor5HplK7miJbnv7vor5Hlr7nosaFcbiAgICogQHJldHVybnMg5Y6f5aeL57+76K+R5qih5p2/5paH5pysXG4gICAqL1xuICBnZXRSYXcoa2V5OiBUcmFuc2xhdGVLZXkpOiBzdHJpbmcge1xuICAgIGlmICh0eXBlb2Yga2V5ID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0VHJhbnNsYXRpb25CeUtleShrZXkpO1xuICAgIH1cblxuICAgIC8vIOW9k2tleeaYr1RyYW5zbGF0aW9u5a+56LGh5pe277yM6I635Y+W5b2T5YmN6K+t6KiA55qE57+76K+R5YC8XG4gICAgY29uc3QgdmFsdWUgPSB0aGlzLmdldFRyYW5zbGF0aW9uQnlPYmplY3Qoa2V5KTtcblxuICAgIC8vIOWmguaenOaJvuWIsOWAvOWImei/lOWbnuWtl+espuS4suW9ouW8j++8jOWQpuWImei/lOWbnkpTT07lrZfnrKbkuLLooajnpLpcbiAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHZhbHVlID09PSBudWxsID8gJ251bGwnIDogU3RyaW5nKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvLyDlpoLmnpzmsqHmnInmib7liLDnv7vor5HvvIzov5Tlm55KU09O5a2X56ym5Liy5b2i5byPXG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGtleSk7XG4gIH1cblxuICAvKipcbiAgICog5YiH5o2i5Yiw5LiL5LiA5Liq5pSv5oyB55qE6K+t6KiA546v5aKDXG4gICAqL1xuICB0b2dnbGVMb2NhbGUoKTogdm9pZCB7XG4gICAgY29uc3QgY3VycmVudEluZGV4ID0gdGhpcy5vcHRpb25zLmxvY2FsZXMuaW5kZXhPZih0aGlzLmxvY2FsZSk7XG5cbiAgICBpZiAoY3VycmVudEluZGV4ID09PSAtMSkge1xuICAgICAgdGhpcy5oYW5kbGVJbnZhbGlkTG9jYWxlKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgbmV4dEluZGV4ID0gKGN1cnJlbnRJbmRleCArIDEpICUgdGhpcy5vcHRpb25zLmxvY2FsZXMubGVuZ3RoO1xuICAgIGNvbnN0IG5leHRMb2NhbGUgPSB0aGlzLm9wdGlvbnMubG9jYWxlc1tuZXh0SW5kZXhdO1xuXG4gICAgaWYgKG5leHRMb2NhbGUgJiYgbmV4dExvY2FsZSAhPT0gdGhpcy5sb2NhbGUpIHtcbiAgICAgIHRoaXMuc2V0TG9jYWxlKG5leHRMb2NhbGUpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiDorr7nva7lvZPliY3or63oqIDnjq/looNcbiAgICogQHBhcmFtIGxvY2FsZSAtIOimgeiuvue9rueahOivreiogOeOr+Wig1xuICAgKi9cbiAgc2V0TG9jYWxlKGxvY2FsZTogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWRMb2NhbGUobG9jYWxlKSkge1xuICAgICAgaWYgKGlzRGV2TW9kZSgpKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICBgSW52YWxpZCBsb2NhbGU6ICR7bG9jYWxlfS4gU3VwcG9ydGVkIGxvY2FsZXM6ICR7dGhpcy5vcHRpb25zLmxvY2FsZXMuam9pbignLCAnKX1gLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKExPQ0FMRV9TVE9SQUdFLCBsb2NhbGUpO1xuICAgIHRoaXMubG9jYWxlID0gbG9jYWxlO1xuICB9XG5cbiAgLyoqXG4gICAqIOaJi+WKqOa3u+WKoOe/u+ivkeWMhVxuICAgKiBAcGFyYW0gdHJhbnNsYXRpb25zIC0g6KaB5re75Yqg55qE57+76K+R5YyFXG4gICAqL1xuICBhZGRUcmFuc2xhdGlvbnModHJhbnNsYXRpb25zOiBUcmFuc2xhdGlvbnMpOiB2b2lkIHtcbiAgICBpZiAoIXRyYW5zbGF0aW9ucyB8fCB0eXBlb2YgdHJhbnNsYXRpb25zICE9PSAnb2JqZWN0Jykge1xuICAgICAgaWYgKGlzRGV2TW9kZSgpKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignSW52YWxpZCB0cmFuc2xhdGlvbnMgb2JqZWN0IHByb3ZpZGVkJyk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8g5byA5Y+R5qih5byP5LiL5qOA5p+l6YeN5aSN57+76K+RXG4gICAgaWYgKGlzRGV2TW9kZSgpICYmIHRoaXMudHJhbnNsYXRpb25zTGlzdC5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLmNoZWNrRm9yRHVwbGljYXRlVHJhbnNsYXRpb25zKHRyYW5zbGF0aW9ucyk7XG4gICAgfVxuXG4gICAgdGhpcy50cmFuc2xhdGlvbnNMaXN0LnB1c2godHJhbnNsYXRpb25zKTtcbiAgICB0aGlzLnRyYW5zbGF0aW9uc0FkZGVkJCQubmV4dCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIOa3u+WKoOi/nOeoi+e/u+ivkeWMhVxuICAgKiBAcGFyYW0gcmVtb3RlVXJsIC0g6L+c56iL57+76K+R5paH5Lu2VVJMXG4gICAqL1xuICBhZGRSZW1vdGVUcmFuc2xhdGlvbnMocmVtb3RlVXJsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIXJlbW90ZVVybCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IG5vcm1hbGl6ZWRVcmwgPSB0aGlzLm5vcm1hbGl6ZVJlbW90ZVVybChyZW1vdGVVcmwpO1xuICAgIGNvbnN0IHJlcXVlc3QkID0gdGhpcy5jcmVhdGVSZW1vdGVUcmFuc2xhdGlvblJlcXVlc3Qobm9ybWFsaXplZFVybCk7XG5cbiAgICByZXF1ZXN0JFxuICAgICAgLnBpcGUoXG4gICAgICAgIHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkJCksXG4gICAgICAgIGZpbmFsaXplKCgpID0+IHtcbiAgICAgICAgICB0aGlzLnRyYW5zbGF0aW9uc0FkZGVkJCQubmV4dCgpO1xuICAgICAgICB9KSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICBuZXh0OiByZW1vdGVUcmFuc2xhdGlvbnMgPT4ge1xuICAgICAgICAgIGlmIChyZW1vdGVUcmFuc2xhdGlvbnMpIHtcbiAgICAgICAgICAgIHRoaXMucmVtb3RlVHJhbnNsYXRpb25zTGlzdC5wdXNoKHJlbW90ZVRyYW5zbGF0aW9ucyk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogZXJyb3IgPT4ge1xuICAgICAgICAgIGlmIChpc0Rldk1vZGUoKSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcbiAgICAgICAgICAgICAgYEZhaWxlZCB0byBsb2FkIHJlbW90ZSB0cmFuc2xhdGlvbnMgZnJvbSAke3JlbW90ZVVybH06YCxcbiAgICAgICAgICAgICAgZXJyb3IsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIOS7jui/nOeoi1VSTOiOt+WPlue/u+ivkeaVsOaNrlxuICAgKiBAcGFyYW0gcmVtb3RlVXJsIC0g6L+c56iLVVJMXG4gICAqIEBwYXJhbSBsb2NhbGUgLSDlj6/pgInnmoTor63oqIDnjq/looPvvIjnlKjkuo5VUkzmqKHmnb/mm7/mjaLvvIlcbiAgICogQHJldHVybnMg57+76K+R5pWw5o2u55qET2JzZXJ2YWJsZVxuICAgKi9cbiAgZmV0Y2hUcmFuc2xhdGlvbihyZW1vdGVVcmw6IHN0cmluZyk6IE9ic2VydmFibGU8VHJhbnNsYXRpb25zPjtcbiAgZmV0Y2hUcmFuc2xhdGlvbihyZW1vdGVVcmw6IHN0cmluZywgbG9jYWxlOiBzdHJpbmcpOiBPYnNlcnZhYmxlPFRyYW5zbGF0aW9uPjtcbiAgZmV0Y2hUcmFuc2xhdGlvbihcbiAgICByZW1vdGVVcmw6IHN0cmluZyxcbiAgICBsb2NhbGU/OiBzdHJpbmcsXG4gICk6IE9ic2VydmFibGU8VHJhbnNsYXRpb25zIHwgVHJhbnNsYXRpb24+IHtcbiAgICB0aGlzLnZhbGlkYXRlRmV0Y2hUcmFuc2xhdGlvblBhcmFtcyhyZW1vdGVVcmwsIGxvY2FsZSk7XG5cbiAgICBjb25zdCB0YXJnZXRVcmwgPSBsb2NhbGVcbiAgICAgID8gcmVtb3RlVXJsLnJlcGxhY2UoTE9DQUxFX1BMQUNFSE9MREVSX1JFR0VYLCBsb2NhbGUpXG4gICAgICA6IHJlbW90ZVVybDtcblxuICAgIHJldHVybiB0aGlzLnBlcmZvcm1UcmFuc2xhdGlvblJlcXVlc3QodGFyZ2V0VXJsKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDojrflj5bliJ3lp4vor63oqIDnjq/looNcbiAgICovXG4gIHByaXZhdGUgZ2V0SW5pdGlhbExvY2FsZShvcHRpb25zOiBUcmFuc2xhdGVPcHRpb25zKTogc3RyaW5nIHtcbiAgICByZXR1cm4gb3B0aW9ucz8ubG9jYWxlIHx8IGdldFVzZXJMYW5ndWFnZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIOiOt+WPluWIneWni+e/u+ivkeWIl+ihqFxuICAgKi9cbiAgcHJpdmF0ZSBnZXRJbml0aWFsaXplVHJhbnNsYXRpb25zKFxuICAgIG9wdGlvbnM6IFRyYW5zbGF0ZU9wdGlvbnMsXG4gICAgdHJhbnNsYXRpb25MaXN0OiBUcmFuc2xhdGlvbnNbXSxcbiAgKTogVHJhbnNsYXRpb25zW10ge1xuICAgIHJldHVybiBbb3B0aW9ucz8udHJhbnNsYXRpb25zLCAuLi4odHJhbnNsYXRpb25MaXN0IHx8IFtdKV0uZmlsdGVyKEJvb2xlYW4pO1xuICB9XG5cbiAgLyoqXG4gICAqIOWKoOi9vei/nOeoi+e/u+ivkVxuICAgKi9cbiAgcHJpdmF0ZSBsb2FkUmVtb3RlVHJhbnNsYXRpb25zKG9wdGlvbnM6IFRyYW5zbGF0ZU9wdGlvbnMpOiB2b2lkIHtcbiAgICBpZiAoIW9wdGlvbnM/LnJlbW90ZVVybCkgcmV0dXJuO1xuXG4gICAgY29uc3QgdXJscyA9IEFycmF5LmlzQXJyYXkob3B0aW9ucy5yZW1vdGVVcmwpXG4gICAgICA/IG9wdGlvbnMucmVtb3RlVXJsXG4gICAgICA6IFtvcHRpb25zLnJlbW90ZVVybF07XG5cbiAgICB1cmxzLmZvckVhY2godXJsID0+IHRoaXMuYWRkUmVtb3RlVHJhbnNsYXRpb25zKHVybCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIOi9rOaNouaooeadv+aVsOaNruS4uiBJQ1Ug5YW85a655qC85byPXG4gICAqIEBwYXJhbSBkYXRhIC0g5qih5p2/5pWw5o2uXG4gICAqIEByZXR1cm5zIElDVSDlhbzlrrnnmoTmlbDmja7lr7nosaFcbiAgICovXG4gIHByaXZhdGUgbm9ybWFsaXplQW5kQ29udmVydFRvSWN1RGF0YShkYXRhOiBUZW1wbGF0ZURhdGEpOiBJY3VEYXRhIHtcbiAgICBpZiAoZGF0YSA9PSBudWxsKSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuXG4gICAgLy8g5aaC5p6c5piv57qv5a+56LGh77yM55u05o6l6L2s5o2i5YW25bGe5oCnXG4gICAgaWYgKHRoaXMuaXNQbGFpblRlbXBsYXRlT2JqZWN0KGRhdGEpKSB7XG4gICAgICByZXR1cm4gdGhpcy5jb252ZXJ0T2JqZWN0VG9JY3VEYXRhKGRhdGEpO1xuICAgIH1cblxuICAgIC8vIOWfuuacrOexu+Wei+OAgeaVsOe7hOOAgURhdGXnrYnljIXoo4XkuLogeyB2YWx1ZTogZGF0YSB9XG4gICAgcmV0dXJuIHsgdmFsdWU6IHRoaXMuY29udmVydFZhbHVlVG9JY3VWYWx1ZShkYXRhKSB9O1xuICB9XG5cbiAgLyoqXG4gICAqIOajgOafpeaYr+WQpuS4uue6r+aooeadv+Wvueixoe+8iOS4jeaYr+aVsOe7hOOAgURhdGXnrYnnibnmrorlr7nosaHvvIlcbiAgICovXG4gIHByaXZhdGUgaXNQbGFpblRlbXBsYXRlT2JqZWN0KFxuICAgIGRhdGE6IFRlbXBsYXRlRGF0YSxcbiAgKTogZGF0YSBpcyBSZWNvcmQ8c3RyaW5nLCBUZW1wbGF0ZURhdGE+IHtcbiAgICByZXR1cm4gKFxuICAgICAgdHlwZW9mIGRhdGEgPT09ICdvYmplY3QnICYmXG4gICAgICBkYXRhICE9PSBudWxsICYmXG4gICAgICAhQXJyYXkuaXNBcnJheShkYXRhKSAmJlxuICAgICAgIShkYXRhIGluc3RhbmNlb2YgRGF0ZSkgJiZcbiAgICAgIGRhdGEuY29uc3RydWN0b3IgPT09IE9iamVjdFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICog6L2s5o2i5a+56LGh55qE5omA5pyJ5bGe5oCn5Li6IElDVSDlhbzlrrnlgLxcbiAgICovXG4gIHByaXZhdGUgY29udmVydE9iamVjdFRvSWN1RGF0YShvYmo6IFJlY29yZDxzdHJpbmcsIFRlbXBsYXRlRGF0YT4pOiBJY3VEYXRhIHtcbiAgICBjb25zdCByZXN1bHQ6IEljdURhdGEgPSB7fTtcblxuICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKG9iaikpIHtcbiAgICAgIGlmICh2YWx1ZSAhPSBudWxsKSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gdGhpcy5jb252ZXJ0VmFsdWVUb0ljdVZhbHVlKHZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIOWwhuWNleS4quWAvOi9rOaNouS4uiBJQ1Ug5YW85a6557G75Z6LXG4gICAqIOaMieeFpyBJQ1UgTWVzc2FnZUZvcm1hdCDop4TojIPvvIzlj6rmlK/mjIEgc3RyaW5nIHwgbnVtYmVyIHwgRGF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBjb252ZXJ0VmFsdWVUb0ljdVZhbHVlKHZhbHVlOiBUZW1wbGF0ZURhdGEpOiBzdHJpbmcgfCBudW1iZXIgfCBEYXRlIHtcbiAgICAvLyBJQ1Ug5Y6f55Sf5pSv5oyB55qE57G75Z6L55u05o6l6L+U5ZueXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvLyDlhbbku5bnsbvlnovovazkuLrlrZfnrKbkuLJcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbicpIHtcbiAgICAgIHJldHVybiBTdHJpbmcodmFsdWUpO1xuICAgIH1cblxuICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgLy8g566A5Y2V5pWw57uE6L2s5Li66YCX5Y+35YiG6ZqU55qE5a2X56ym5LiyXG4gICAgICByZXR1cm4gdmFsdWUubWFwKGl0ZW0gPT4gU3RyaW5nKGl0ZW0gPz8gJycpKS5qb2luKCcsICcpO1xuICAgIH1cblxuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuICdudWxsJztcbiAgICB9XG5cbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIC8vIOWvueixoei9rOS4uiBKU09OIOWtl+espuS4slxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBTdHJpbmcodmFsdWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBTdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIOWkhOeQhuaooeadv+mUmeivr1xuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVUZW1wbGF0ZUVycm9yKGtleTogVHJhbnNsYXRlS2V5LCBlcnJvcjogYW55KTogdm9pZCB7XG4gICAgY29uc3Qga2V5U3RyID0gdHlwZW9mIGtleSA9PT0gJ3N0cmluZycgPyBrZXkgOiAnW29iamVjdF0nO1xuICAgIGNvbnN0IG1lc3NhZ2UgPSBgVGhlIHRyYW5zbGF0aW9uIGtleSAnJHtrZXlTdHJ9JyBpcyBtaXNzaW5nIHRoZSBuZWNlc3NhcnkgcGFyYW1ldGVycy5gO1xuICAgIGlmIChpc0Rldk1vZGUoKSkge1xuICAgICAgY29uc29sZS5lcnJvcihtZXNzYWdlLCBlcnJvcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUud2FybihtZXNzYWdlLCBlcnJvcik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIOWwhuS8oOe7n+eahCB7eyBrZXkgfX0g6K+t5rOV6L2s5o2i5Li6IElDVSB7a2V5fSDmoLzlvI9cbiAgICog5ZCM5pe25L+d5oyB5bey5pyJ55qEIElDVSDmoLzlvI/kuI3lj5hcbiAgICogQHBhcmFtIG1lc3NhZ2UgLSDljp/lp4vmtojmga/mqKHmnb9cbiAgICogQHJldHVybnMg6L2s5o2i5ZCO55qEIElDVSDmoLzlvI/mtojmga9cbiAgICovXG4gIHByaXZhdGUgY29udmVydFRvSWN1Rm9ybWF0KG1lc3NhZ2U6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgLy8g5bCGIHt7IGtleSB9fSDovazmjaLkuLoge2tleX1cbiAgICAvLyDmlK/mjIHnqbrmoLzvvJp7eyBrZXkgfX0gLT4ge2tleX3vvIzkvYbljrvmjonlhoXpg6jnmoTnqbrmoLxcbiAgICByZXR1cm4gbWVzc2FnZS5yZXBsYWNlKC9cXHtcXHsoW159XSspXFx9XFx9L2csIChfLCBjb250ZW50KSA9PiB7XG4gICAgICByZXR1cm4gYHske2NvbnRlbnQudHJpbSgpfX1gO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIOS9v+eUqCBJQ1UgbWVzc2FnZSBmb3JtYXQg5qC85byP5YyW5paH5pysXG4gICAqL1xuICBwcml2YXRlIGZvcm1hdEljdU1lc3NhZ2UobWVzc2FnZTogc3RyaW5nLCBpY3VEYXRhOiBJY3VEYXRhKTogc3RyaW5nIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgbWVzc2FnZUZvcm1hdCA9IG5ldyBJbnRsTWVzc2FnZUZvcm1hdChtZXNzYWdlLCB0aGlzLmxvY2FsZSk7XG4gICAgICByZXR1cm4gbWVzc2FnZUZvcm1hdC5mb3JtYXQoaWN1RGF0YSkgYXMgc3RyaW5nO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoaXNEZXZNb2RlKCkpIHtcbiAgICAgICAgY29uc29sZS53YXJuKGBJQ1UgbWVzc2FnZSBmb3JtYXR0aW5nIGZhaWxlZCBmb3IgXCIke21lc3NhZ2V9XCI6YCwgZXJyb3IpO1xuICAgICAgfVxuICAgICAgLy8g6ZmN57qn5aSE55CG77ya6L+U5Zue5Y6f5aeL5raI5oGvXG4gICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICog5qC85byP5YyW5pWw5a2XXG4gICAqIEBwYXJhbSB2YWx1ZSAtIOimgeagvOW8j+WMlueahOaVsOWtl1xuICAgKiBAcGFyYW0gb3B0aW9ucyAtIOagvOW8j+WMlumAiemhuVxuICAgKiBAcmV0dXJucyDmoLzlvI/ljJblkI7nmoTmlbDlrZflrZfnrKbkuLJcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogZm9ybWF0TnVtYmVyKDEyMzQuNTYpIC8vIFwiMSwyMzQuNTZcIlxuICAgKiBmb3JtYXROdW1iZXIoMC44NSwgeyBzdHlsZTogJ3BlcmNlbnQnIH0pIC8vIFwiODUlXCJcbiAgICogZm9ybWF0TnVtYmVyKDEyMzQuNTYsIHsgc3R5bGU6ICdjdXJyZW5jeScsIGN1cnJlbmN5OiAnQ05ZJyB9KSAvLyBcIsKlMSwyMzQuNTZcIlxuICAgKi9cbiAgZm9ybWF0TnVtYmVyKHZhbHVlOiBudW1iZXIsIG9wdGlvbnM6IEludGwuTnVtYmVyRm9ybWF0T3B0aW9ucyA9IHt9KTogc3RyaW5nIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIG5ldyBJbnRsLk51bWJlckZvcm1hdCh0aGlzLmxvY2FsZSwgb3B0aW9ucykuZm9ybWF0KHZhbHVlKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGlzRGV2TW9kZSgpKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihgTnVtYmVyIGZvcm1hdHRpbmcgZmFpbGVkIGZvciB2YWx1ZSAke3ZhbHVlfTpgLCBlcnJvcik7XG4gICAgICB9XG4gICAgICByZXR1cm4gdmFsdWUudG9TdHJpbmcoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICog5qC85byP5YyW6LSn5biBXG4gICAqIEBwYXJhbSB2YWx1ZSAtIOimgeagvOW8j+WMlueahOmHkeminVxuICAgKiBAcGFyYW0gY3VycmVuY3kgLSDotKfluIHku6PnoIHvvIzpu5jorqTkuLogQ05ZXG4gICAqIEBwYXJhbSBvcHRpb25zIC0g5YW25LuW5qC85byP5YyW6YCJ6aG5XG4gICAqIEByZXR1cm5zIOagvOW8j+WMluWQjueahOi0p+W4geWtl+espuS4slxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBmb3JtYXRDdXJyZW5jeSgxMjM0LjU2KSAvLyBlbi1VUzogXCJDTsKlMSwyMzQuNTZcIiwgemgtQ046IFwiwqUxLDIzNC41NlwiXG4gICAqIGZvcm1hdEN1cnJlbmN5KDEyMzQuNTYsICdVU0QnKSAvLyBlbi1VUzogXCIkMSwyMzQuNTZcIiwgemgtQ046IFwiVVMkMSwyMzQuNTZcIlxuICAgKi9cbiAgZm9ybWF0Q3VycmVuY3koXG4gICAgdmFsdWU6IG51bWJlcixcbiAgICBjdXJyZW5jeTogc3RyaW5nID0gJ0NOWScsXG4gICAgb3B0aW9uczogT21pdDxJbnRsLk51bWJlckZvcm1hdE9wdGlvbnMsICdzdHlsZScgfCAnY3VycmVuY3knPiA9IHt9LFxuICApOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmZvcm1hdE51bWJlcih2YWx1ZSwge1xuICAgICAgc3R5bGU6ICdjdXJyZW5jeScsXG4gICAgICBjdXJyZW5jeSxcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICog5qC85byP5YyW55m+5YiG5q+UXG4gICAqIEBwYXJhbSB2YWx1ZSAtIOimgeagvOW8j+WMlueahOWAvO+8iDAuODUg6KGo56S6IDg1Je+8iVxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIOagvOW8j+WMlumAiemhuVxuICAgKiBAcmV0dXJucyDmoLzlvI/ljJblkI7nmoTnmb7liIbmr5TlrZfnrKbkuLJcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogZm9ybWF0UGVyY2VudCgwLjg1KSAvLyBcIjg1JVwiXG4gICAqIGZvcm1hdFBlcmNlbnQoMC44NTY3LCB7IG1pbmltdW1GcmFjdGlvbkRpZ2l0czogMiB9KSAvLyBcIjg1LjY3JVwiXG4gICAqL1xuICBmb3JtYXRQZXJjZW50KFxuICAgIHZhbHVlOiBudW1iZXIsXG4gICAgb3B0aW9uczogT21pdDxJbnRsLk51bWJlckZvcm1hdE9wdGlvbnMsICdzdHlsZSc+ID0ge30sXG4gICk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybWF0TnVtYmVyKHZhbHVlLCB7XG4gICAgICBzdHlsZTogJ3BlcmNlbnQnLFxuICAgICAgLi4ub3B0aW9ucyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiDmoLzlvI/ljJbml6XmnJ9cbiAgICogQHBhcmFtIGRhdGUgLSDopoHmoLzlvI/ljJbnmoTml6XmnJ9cbiAgICogQHBhcmFtIG9wdGlvbnMgLSBJbnRsLkRhdGVUaW1lRm9ybWF0T3B0aW9ucyDmoLzlvI/phY3nva5cbiAgICogQHJldHVybnMg5qC85byP5YyW5ZCO55qE5pel5pyf5a2X56ym5LiyXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGZvcm1hdERhdGUobmV3IERhdGUoKSkgLy8gZW4tVVM6IFwiMDEvMDEvMjAyNVwiLCB6aC1DTjogXCIyMDI1LzAxLzAxXCJcbiAgICogZm9ybWF0RGF0ZShuZXcgRGF0ZSgpLCB7IGRhdGVTdHlsZTogJ2Z1bGwnIH0pIC8vIFwiMjAyNOW5tDjmnIgyMOaXpeaYn+acn+S6jFwiXG4gICAqIGZvcm1hdERhdGUobmV3IERhdGUoKSwgeyB5ZWFyOiAnbnVtZXJpYycsIG1vbnRoOiAnMi1kaWdpdCcsIGRheTogJzItZGlnaXQnIH0pIC8vIOagueaNrmxvY2FsZeagvOW8j+WMllxuICAgKiBmb3JtYXREYXRlKG5ldyBEYXRlKCksIHsgeWVhcjogJ251bWVyaWMnLCBtb250aDogJ2xvbmcnIH0pIC8vIFwiMjAyNOW5tDjmnIhcIlxuICAgKi9cbiAgZm9ybWF0RGF0ZShcbiAgICBkYXRlOiBEYXRlIHwgc3RyaW5nIHwgbnVtYmVyLFxuICAgIG9wdGlvbnM6IEludGwuRGF0ZVRpbWVGb3JtYXRPcHRpb25zID0ge1xuICAgICAgeWVhcjogJ251bWVyaWMnLFxuICAgICAgbW9udGg6ICcyLWRpZ2l0JyxcbiAgICAgIGRheTogJzItZGlnaXQnLFxuICAgIH0sXG4gICk6IHN0cmluZyB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGRhdGVPYmogPSBuZXcgRGF0ZShkYXRlKTtcbiAgICAgIGlmIChpc05hTihkYXRlT2JqLmdldFRpbWUoKSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGRhdGUnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLmZvcm1hdERhdGVCeU9wdGlvbnMoZGF0ZU9iaiwgb3B0aW9ucyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChpc0Rldk1vZGUoKSkge1xuICAgICAgICBjb25zb2xlLndhcm4oYERhdGUgZm9ybWF0dGluZyBmYWlsZWQgZm9yIGRhdGUgJHtkYXRlfTpgLCBlcnJvcik7XG4gICAgICB9XG4gICAgICByZXR1cm4gU3RyaW5nKGRhdGUpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiDmoLzlvI/ljJbml6XmnJ/lkozml7bpl7RcbiAgICogQHBhcmFtIGRhdGUgLSDopoHmoLzlvI/ljJbnmoTml6XmnJ/ml7bpl7RcbiAgICogQHBhcmFtIG9wdGlvbnMgLSBJbnRsLkRhdGVUaW1lRm9ybWF0T3B0aW9ucyDmoLzlvI/phY3nva5cbiAgICogQHJldHVybnMg5qC85byP5YyW5ZCO55qE5pel5pyf5pe26Ze05a2X56ym5LiyXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGZvcm1hdERhdGVUaW1lKG5ldyBEYXRlKCkpIC8vIGVuLVVTOiBcIjAxLzAxLzIwMjUsIDE0OjMwOjAwXCIsIHpoLUNOOiBcIjIwMjUvMDEvMDEgMTQ6MzA6MDBcIlxuICAgKiBmb3JtYXREYXRlVGltZShuZXcgRGF0ZSgpLCB7IGRhdGVTdHlsZTogJ21lZGl1bScsIHRpbWVTdHlsZTogJ3Nob3J0JyB9KSAvLyBcIjIwMjTlubQ45pyIMjDml6UgMTQ6MzBcIlxuICAgKiBmb3JtYXREYXRlVGltZShuZXcgRGF0ZSgpLCB7IHllYXI6ICdudW1lcmljJywgbW9udGg6ICcyLWRpZ2l0JywgZGF5OiAnMi1kaWdpdCcsIGhvdXI6ICcyLWRpZ2l0JywgbWludXRlOiAnMi1kaWdpdCcsIHNlY29uZDogJzItZGlnaXQnLCBob3VyMTI6IGZhbHNlIH0pIC8vIOagueaNrmxvY2FsZeagvOW8j+WMllxuICAgKi9cbiAgZm9ybWF0RGF0ZVRpbWUoXG4gICAgZGF0ZTogRGF0ZSB8IHN0cmluZyB8IG51bWJlcixcbiAgICBvcHRpb25zOiBJbnRsLkRhdGVUaW1lRm9ybWF0T3B0aW9ucyA9IHtcbiAgICAgIHllYXI6ICdudW1lcmljJyxcbiAgICAgIG1vbnRoOiAnMi1kaWdpdCcsXG4gICAgICBkYXk6ICcyLWRpZ2l0JyxcbiAgICAgIGhvdXI6ICcyLWRpZ2l0JyxcbiAgICAgIG1pbnV0ZTogJzItZGlnaXQnLFxuICAgICAgc2Vjb25kOiAnMi1kaWdpdCcsXG4gICAgICBob3VyMTI6IGZhbHNlLFxuICAgIH0sXG4gICk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybWF0RGF0ZShkYXRlLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDmoLzlvI/ljJbnm7jlr7nml7bpl7RcbiAgICogQHBhcmFtIHZhbHVlIC0g5pe26Ze05beu5YC877yI5pWw5a2X77yJ5oiW5pel5pyf5a+56LGhXG4gICAqIEBwYXJhbSB1bml0IC0g5pe26Ze05Y2V5L2N77yI5b2TdmFsdWXkuLrmlbDlrZfml7blv4Xpobvmj5DkvpvvvIlcbiAgICogQHBhcmFtIG9wdGlvbnMgLSDmoLzlvI/ljJbpgInpoblcbiAgICogQHJldHVybnMg5qC85byP5YyW5ZCO55qE55u45a+55pe26Ze05a2X56ym5LiyXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIC8vIOaJi+WKqOaMh+WumuWNleS9jVxuICAgKiBmb3JtYXRSZWxhdGl2ZVRpbWUoLTEsICdkYXknKSAvLyBlbi1VUzogXCJ5ZXN0ZXJkYXlcIiwgemgtQ046IFwi5pio5aSpXCJcbiAgICogZm9ybWF0UmVsYXRpdmVUaW1lKDIsICdob3VyJykgLy8gZW4tVVM6IFwiaW4gMiBob3Vyc1wiLCB6aC1DTjogXCIy5bCP5pe25ZCOXCJcbiAgICogZm9ybWF0UmVsYXRpdmVUaW1lKC0zMCwgJ21pbnV0ZScpIC8vIGVuLVVTOiBcIjMwIG1pbnV0ZXMgYWdvXCIsIHpoLUNOOiBcIjMw5YiG6ZKf5YmNXCJcbiAgICpcbiAgICogLy8g6Ieq5Yqo6K6h566X5Y2V5L2NXG4gICAqIGZvcm1hdFJlbGF0aXZlVGltZShuZXcgRGF0ZShEYXRlLm5vdygpIC0gNjAwMDApKSAvLyBcIjEgbWludXRlIGFnb1wiXG4gICAqIGZvcm1hdFJlbGF0aXZlVGltZShuZXcgRGF0ZShEYXRlLm5vdygpICsgNzIwMDAwMCkpIC8vIFwiaW4gMiBob3Vyc1wiXG4gICAqIGZvcm1hdFJlbGF0aXZlVGltZShuZXcgRGF0ZShEYXRlLm5vdygpIC0gODY0MDAwMDApKSAvLyBcInllc3RlcmRheVwiXG4gICAqL1xuICBmb3JtYXRSZWxhdGl2ZVRpbWUoXG4gICAgdmFsdWU6IERhdGUsXG4gICAgb3B0aW9ucz86IEludGwuUmVsYXRpdmVUaW1lRm9ybWF0T3B0aW9ucyxcbiAgKTogc3RyaW5nO1xuXG4gIGZvcm1hdFJlbGF0aXZlVGltZShcbiAgICB2YWx1ZTogbnVtYmVyLFxuICAgIHVuaXQ6IEludGwuUmVsYXRpdmVUaW1lRm9ybWF0VW5pdCxcbiAgICBvcHRpb25zPzogSW50bC5SZWxhdGl2ZVRpbWVGb3JtYXRPcHRpb25zLFxuICApOiBzdHJpbmc7XG5cbiAgZm9ybWF0UmVsYXRpdmVUaW1lKFxuICAgIHZhbHVlOiBudW1iZXIgfCBEYXRlLFxuICAgIHVuaXRPck9wdGlvbnM/OlxuICAgICAgfCBJbnRsLlJlbGF0aXZlVGltZUZvcm1hdFVuaXRcbiAgICAgIHwgSW50bC5SZWxhdGl2ZVRpbWVGb3JtYXRPcHRpb25zLFxuICAgIG9wdGlvbnM6IEludGwuUmVsYXRpdmVUaW1lRm9ybWF0T3B0aW9ucyA9IHsgbnVtZXJpYzogJ2F1dG8nIH0sXG4gICk6IHN0cmluZyB7XG4gICAgdHJ5IHtcbiAgICAgIGxldCBmaW5hbFZhbHVlOiBudW1iZXI7XG4gICAgICBsZXQgZmluYWxVbml0OiBJbnRsLlJlbGF0aXZlVGltZUZvcm1hdFVuaXQ7XG4gICAgICBsZXQgZmluYWxPcHRpb25zOiBJbnRsLlJlbGF0aXZlVGltZUZvcm1hdE9wdGlvbnM7XG5cbiAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgLy8g6Ieq5Yqo6K6h566X5pe26Ze05beu5ZKM5Y2V5L2NXG4gICAgICAgIGNvbnN0IHsgdmFsdWU6IGNhbGN1bGF0ZWRWYWx1ZSwgdW5pdDogY2FsY3VsYXRlZFVuaXQgfSA9XG4gICAgICAgICAgdGhpcy5jYWxjdWxhdGVSZWxhdGl2ZVRpbWUodmFsdWUpO1xuICAgICAgICBmaW5hbFZhbHVlID0gY2FsY3VsYXRlZFZhbHVlO1xuICAgICAgICBmaW5hbFVuaXQgPSBjYWxjdWxhdGVkVW5pdDtcbiAgICAgICAgZmluYWxPcHRpb25zID1cbiAgICAgICAgICAodW5pdE9yT3B0aW9ucyBhcyBJbnRsLlJlbGF0aXZlVGltZUZvcm1hdE9wdGlvbnMpIHx8IG9wdGlvbnM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyDkvb/nlKjmj5DkvpvnmoTmlbDlgLzlkozljZXkvY1cbiAgICAgICAgZmluYWxWYWx1ZSA9IHZhbHVlO1xuICAgICAgICBmaW5hbFVuaXQgPSB1bml0T3JPcHRpb25zIGFzIEludGwuUmVsYXRpdmVUaW1lRm9ybWF0VW5pdDtcbiAgICAgICAgZmluYWxPcHRpb25zID0gb3B0aW9ucztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5ldyBJbnRsLlJlbGF0aXZlVGltZUZvcm1hdCh0aGlzLmxvY2FsZSwgZmluYWxPcHRpb25zKS5mb3JtYXQoXG4gICAgICAgIGZpbmFsVmFsdWUsXG4gICAgICAgIGZpbmFsVW5pdCxcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChpc0Rldk1vZGUoKSkge1xuICAgICAgICBjb25zb2xlLndhcm4oYFJlbGF0aXZlIHRpbWUgZm9ybWF0dGluZyBmYWlsZWQgZm9yICR7dmFsdWV9OmAsIGVycm9yKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIERhdGVcbiAgICAgICAgPyB2YWx1ZS50b0xvY2FsZVN0cmluZyh0aGlzLmxvY2FsZSlcbiAgICAgICAgOiBgJHt2YWx1ZX1gO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiDmoLnmja7ml6XmnJ/orqHnrpfnm7jlr7nml7bpl7Tlt67lgLzlkozmnIDlkIjpgILnmoTljZXkvY1cbiAgICogQHBhcmFtIGRhdGUgLSDnm67moIfml6XmnJ9cbiAgICogQHJldHVybnMg5YyF5ZCr5pe26Ze05beu5YC85ZKM5Y2V5L2N55qE5a+56LGhXG4gICAqL1xuICBwcml2YXRlIGNhbGN1bGF0ZVJlbGF0aXZlVGltZShkYXRlOiBEYXRlKToge1xuICAgIHZhbHVlOiBudW1iZXI7XG4gICAgdW5pdDogSW50bC5SZWxhdGl2ZVRpbWVGb3JtYXRVbml0O1xuICB9IHtcbiAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xuICAgIGNvbnN0IGRpZmZNcyA9IGRhdGUuZ2V0VGltZSgpIC0gbm93LmdldFRpbWUoKTtcbiAgICBjb25zdCBhYnNEaWZmTXMgPSBNYXRoLmFicyhkaWZmTXMpO1xuXG4gICAgLy8g5pe26Ze05Y2V5L2N6ZiI5YC877yI5q+r56eS77yJXG4gICAgY29uc3QgTUlOVVRFX01TID0gNjAgKiAxMDAwO1xuICAgIGNvbnN0IEhPVVJfTVMgPSA2MCAqIE1JTlVURV9NUztcbiAgICBjb25zdCBEQVlfTVMgPSAyNCAqIEhPVVJfTVM7XG5cbiAgICAvLyDmoLnmja7ml7bpl7Tlt67pgInmi6nlkIjpgILnmoTljZXkvY3vvIzmnIDlpKfljZXkvY3kuLpkYXlcbiAgICBpZiAoYWJzRGlmZk1zID49IERBWV9NUykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdmFsdWU6IE1hdGgucm91bmQoZGlmZk1zIC8gREFZX01TKSxcbiAgICAgICAgdW5pdDogJ2RheScsXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAoYWJzRGlmZk1zID49IEhPVVJfTVMpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHZhbHVlOiBNYXRoLnJvdW5kKGRpZmZNcyAvIEhPVVJfTVMpLFxuICAgICAgICB1bml0OiAnaG91cicsXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAoYWJzRGlmZk1zID49IE1JTlVURV9NUykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdmFsdWU6IE1hdGgucm91bmQoZGlmZk1zIC8gTUlOVVRFX01TKSxcbiAgICAgICAgdW5pdDogJ21pbnV0ZScsXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgdmFsdWU6IE1hdGgucm91bmQoZGlmZk1zIC8gMTAwMCksXG4gICAgICB1bml0OiAnc2Vjb25kJyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIOagueaNruaXpeacn+agvOW8j+mFjee9ruagvOW8j+WMluaXpeacn1xuICAgKiDkvb/nlKjmoIflh4YgSW50bC5EYXRlVGltZUZvcm1hdE9wdGlvbnMg56Gu5L+d5qC85byP5Y+v6aKE5rWL5oCnXG4gICAqL1xuICBwcml2YXRlIGZvcm1hdERhdGVCeU9wdGlvbnMoXG4gICAgZGF0ZTogRGF0ZSxcbiAgICBvcHRpb25zOiBJbnRsLkRhdGVUaW1lRm9ybWF0T3B0aW9ucyxcbiAgKTogc3RyaW5nIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIG5ldyBJbnRsLkRhdGVUaW1lRm9ybWF0KHRoaXMubG9jYWxlLCBvcHRpb25zKS5mb3JtYXQoZGF0ZSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChpc0Rldk1vZGUoKSkge1xuICAgICAgICBjb25zb2xlLndhcm4oYERhdGUgZm9ybWF0dGluZyBmYWlsZWQ6YCwgZXJyb3IpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGRhdGUudG9JU09TdHJpbmcoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICog6YCa6L+H5a2X56ym5Liy6ZSu6I635Y+W57+76K+RXG4gICAqL1xuICBwcml2YXRlIGdldFRyYW5zbGF0aW9uQnlLZXkoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnJlc29sdmVUcmFuc2xhdGlvbihrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIOmAmui/h+e/u+ivkeWvueixoeiOt+WPlue/u+ivkeWAvFxuICAgKi9cbiAgcHJpdmF0ZSBnZXRUcmFuc2xhdGlvbkJ5T2JqZWN0KFxuICAgIHRyYW5zbGF0aW9uT2JqOiBUcmFuc2xhdGlvbixcbiAgKTogVHJhbnNsYXRpb25WYWx1ZSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0VHJhbnNsYXRpb25WYWx1ZSh0cmFuc2xhdGlvbk9iaiwgdGhpcy5sb2NhbGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIOWkhOeQhuaXoOaViOivreiogOeOr+Wig1xuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVJbnZhbGlkTG9jYWxlKCk6IHZvaWQge1xuICAgIGlmIChpc0Rldk1vZGUoKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignYGxvY2FsZXNgIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZCBjb3JyZWN0bHknKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICog6aqM6K+B6K+t6KiA546v5aKD5piv5ZCm5pyJ5pWIXG4gICAqL1xuICBwcml2YXRlIGlzVmFsaWRMb2NhbGUobG9jYWxlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmxvY2FsZXMuaW5jbHVkZXMobG9jYWxlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDmo4Dmn6Xph43lpI3nv7vor5HvvIjlvIDlj5HmqKHlvI/vvIlcbiAgICovXG4gIHByaXZhdGUgY2hlY2tGb3JEdXBsaWNhdGVUcmFuc2xhdGlvbnMobmV3VHJhbnNsYXRpb25zOiBUcmFuc2xhdGlvbnMpOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IGV4aXN0aW5nVHJhbnNsYXRpb25zIG9mIHRoaXMudHJhbnNsYXRpb25zTGlzdCkge1xuICAgICAgT2JqZWN0LmtleXMobmV3VHJhbnNsYXRpb25zKS5mb3JFYWNoKGxvY2FsZSA9PiB7XG4gICAgICAgIGlmIChleGlzdGluZ1RyYW5zbGF0aW9uc1tsb2NhbGVdKSB7XG4gICAgICAgICAgdGhpcy5jb21wYXJlVHJhbnNsYXRpb25LZXlzKFxuICAgICAgICAgICAgbG9jYWxlLFxuICAgICAgICAgICAgbmV3VHJhbnNsYXRpb25zW2xvY2FsZV0sXG4gICAgICAgICAgICBleGlzdGluZ1RyYW5zbGF0aW9uc1tsb2NhbGVdLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiDmoIflh4bljJbov5znqItVUkxcbiAgICovXG4gIHByaXZhdGUgbm9ybWFsaXplUmVtb3RlVXJsKHJlbW90ZVVybDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZW1vdGVVcmwgPSB0aGlzLmNsZWFuVXJsKHJlbW90ZVVybCk7XG4gICAgY29uc3QgaXNBYnNvbHV0ZSA9IGlzQWJzb2x1dGVVcmwocmVtb3RlVXJsKTtcbiAgICBjb25zdCBpc0FwaUdhdGVXYXlSZXF1ZXN0ID0gcmVtb3RlVXJsLnN0YXJ0c1dpdGgoQVBJX0dBVEVXQVkpO1xuXG4gICAgLy8g5byA5Y+R5qih5byP5LiL6L+b6KGMVVJM6aqM6K+BXG4gICAgaWYgKGlzRGV2TW9kZSgpKSB7XG4gICAgICB0aGlzLnZhbGlkYXRlUmVtb3RlVXJsKHJlbW90ZVVybCwgaXNBYnNvbHV0ZSk7XG4gICAgfVxuXG4gICAgLy8g55u45a+5VVJM6L2s5o2i5Li657ud5a+5VVJMXG4gICAgaWYgKCFpc0Fic29sdXRlICYmICFpc0FwaUdhdGVXYXlSZXF1ZXN0KSB7XG4gICAgICBjb25zdCBiYXNlVXJsID0gdGhpcy5iYXNlSHJlZi5lbmRzV2l0aCgnLycpXG4gICAgICAgID8gdGhpcy5iYXNlSHJlZlxuICAgICAgICA6IGAke3RoaXMuYmFzZUhyZWZ9L2A7XG4gICAgICByZXR1cm4gYCR7YmFzZVVybH0ke3JlbW90ZVVybH1gO1xuICAgIH1cblxuICAgIHJldHVybiByZW1vdGVVcmw7XG4gIH1cblxuICAvKipcbiAgICog5riF55CGVVJM77yI56e76ZmkaGFzaOeJh+aute+8iVxuICAgKi9cbiAgcHJpdmF0ZSBjbGVhblVybCh1cmw6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGhlYWQodXJsLnNwbGl0KC8jLykpIHx8IHVybDtcbiAgfVxuXG4gIC8qKlxuICAgKiDpqozor4Hov5znqItVUkzvvIjlvIDlj5HmqKHlvI/vvIlcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVSZW1vdGVVcmwocmVtb3RlVXJsOiBzdHJpbmcsIGlzQWJzb2x1dGU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAoIWlzQWJzb2x1dGUgJiYgKCF0aGlzLmJhc2VIcmVmIHx8ICFpc0Fic29sdXRlVXJsKHRoaXMuYmFzZUhyZWYpKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICAgJ2Fic29sdXRlIGJhc2UgaHJlZiBpcyByZXF1aXJlZCBmb3IgcmVsYXRpdmUgcmVtb3RlIHVybCcsXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChyZW1vdGVVcmwuc3BsaXQoJz8nKVswXS5pbmNsdWRlcygnLi8nKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICAgJ2RvIG5vdCB1c2UgYW55IGRvdCB3aXRoIHNsYXNoIGZvciByZWxhdGl2ZSB1cmwgd2hpY2ggc2hvdWxkIGFsd2F5cyBiYXNlIGZyb20gYmFzZSBocmVmJyxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIOWIm+W7uui/nOeoi+e/u+ivkeivt+axglxuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVSZW1vdGVUcmFuc2xhdGlvblJlcXVlc3QoXG4gICAgbm9ybWFsaXplZFVybDogc3RyaW5nLFxuICApOiBPYnNlcnZhYmxlPFRyYW5zbGF0aW9ucz4ge1xuICAgIGlmIChMT0NBTEVfUExBQ0VIT0xERVJfUkVHRVgudGVzdChub3JtYWxpemVkVXJsKSkge1xuICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlTXVsdGlMb2NhbGVSZXF1ZXN0KG5vcm1hbGl6ZWRVcmwpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jcmVhdGVTaW5nbGVMb2NhbGVSZXF1ZXN0KG5vcm1hbGl6ZWRVcmwpO1xuICB9XG5cbiAgLyoqXG4gICAqIOWIm+W7uuWkmuivreiogOivt+axglxuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVNdWx0aUxvY2FsZVJlcXVlc3QoXG4gICAgdXJsVGVtcGxhdGU6IHN0cmluZyxcbiAgKTogT2JzZXJ2YWJsZTxUcmFuc2xhdGlvbnM+IHtcbiAgICBjb25zdCByZXF1ZXN0cyA9IHRoaXMub3B0aW9ucy5sb2NhbGVzLm1hcChsb2NhbGUgPT5cbiAgICAgIHRoaXMuZmV0Y2hUcmFuc2xhdGlvbih1cmxUZW1wbGF0ZSwgbG9jYWxlKS5waXBlKFxuICAgICAgICBjYXRjaEVycm9yKGVycm9yID0+IHtcbiAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLmxvb3NlKSB7XG4gICAgICAgICAgICBjb25zdCBsb29zZUxvY2FsZSA9IHRoaXMuZXh0cmFjdExvb3NlTG9jYWxlKGxvY2FsZSk7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgIGxvY2FsZSAhPT0gbG9vc2VMb2NhbGUgJiZcbiAgICAgICAgICAgICAgIXRoaXMub3B0aW9ucy5sb2NhbGVzLmluY2x1ZGVzKGxvb3NlTG9jYWxlKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLmZldGNoVHJhbnNsYXRpb24odXJsVGVtcGxhdGUsIGxvb3NlTG9jYWxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGlzRGV2TW9kZSgpID8gdGhyb3dFcnJvcigoKSA9PiBlcnJvcikgOiBFTVBUWTtcbiAgICAgICAgfSksXG4gICAgICAgIGZpbHRlcihpc1BsYWluT2JqZWN0KSxcbiAgICAgICAgbWFwKFxuICAgICAgICAgICh0cmFuc2xhdGlvbjogVHJhbnNsYXRpb24pID0+XG4gICAgICAgICAgICAoeyBbbG9jYWxlXTogdHJhbnNsYXRpb24gfSkgYXMgVHJhbnNsYXRpb25zLFxuICAgICAgICApLFxuICAgICAgKSxcbiAgICApO1xuXG4gICAgcmV0dXJuIGZvcmtKb2luKHJlcXVlc3RzKS5waXBlKFxuICAgICAgbWFwKHJlc3VsdHMgPT5cbiAgICAgICAgcmVzdWx0cy5yZWR1Y2UoKGFjYywgY3VycikgPT4gT2JqZWN0LmFzc2lnbihhY2MsIGN1cnIpLCB7fSksXG4gICAgICApLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICog5Yib5bu65Y2V6K+t6KiA6K+35rGCXG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZVNpbmdsZUxvY2FsZVJlcXVlc3QodXJsOiBzdHJpbmcpOiBPYnNlcnZhYmxlPFRyYW5zbGF0aW9ucz4ge1xuICAgIHJldHVybiB0aGlzLnBlcmZvcm1UcmFuc2xhdGlvblJlcXVlc3QodXJsKS5waXBlKFxuICAgICAgY2F0Y2hFcnJvcihlcnJvciA9PiAoaXNEZXZNb2RlKCkgPyB0aHJvd0Vycm9yKCgpID0+IGVycm9yKSA6IEVNUFRZKSksXG4gICAgKSBhcyBPYnNlcnZhYmxlPFRyYW5zbGF0aW9ucz47XG4gIH1cblxuICAvKipcbiAgICog5omn6KGM57+76K+R6K+35rGCXG4gICAqL1xuICBwcml2YXRlIHBlcmZvcm1UcmFuc2xhdGlvblJlcXVlc3QodXJsOiBzdHJpbmcpOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgIGNvbnN0IGlzSlNPTiA9IHVybC5lbmRzV2l0aCgnLmpzb24nKTtcbiAgICBjb25zdCBpc0FwaUdhdGVXYXlSZXF1ZXN0ID0gdXJsLnN0YXJ0c1dpdGgoQVBJX0dBVEVXQVkpO1xuICAgIGNvbnN0IHJlc3BvbnNlVHlwZSA9IGlzSlNPTiA/ICdqc29uJyA6ICd0ZXh0JztcblxuICAgIGlmIChpc0FwaUdhdGVXYXlSZXF1ZXN0KSB7XG4gICAgICByZXR1cm4gdGhpcy5odHRwXG4gICAgICAgIC5yZXF1ZXN0KCdHRVQnLCB1cmwsIHsgcmVzcG9uc2VUeXBlIH0pXG4gICAgICAgIC5waXBlKG1hcChib2R5ID0+IChpc0pTT04gPyBib2R5IDogcGFyc2UoYm9keSkpKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFqYXgoeyB1cmwsIHJlc3BvbnNlVHlwZSB9KS5waXBlKFxuICAgICAgbWFwKCh7IHJlc3BvbnNlIH0pID0+IChpc0pTT04gPyByZXNwb25zZSA6IHBhcnNlKHJlc3BvbnNlIGFzIHN0cmluZykpKSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIOmqjOivgWZldGNoVHJhbnNsYXRpb27lj4LmlbBcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVGZXRjaFRyYW5zbGF0aW9uUGFyYW1zKFxuICAgIHJlbW90ZVVybDogc3RyaW5nLFxuICAgIGxvY2FsZT86IHN0cmluZyxcbiAgKTogdm9pZCB7XG4gICAgaWYgKGlzRGV2TW9kZSgpICYmIExPQ0FMRV9QTEFDRUhPTERFUl9SRUdFWC50ZXN0KHJlbW90ZVVybCkgJiYgIWxvY2FsZSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICAgJ2Bsb2NhbGVgIGlzIHJlcXVpcmVkIHNpbmNlIHRoZSBwcm92aWRlZCByZW1vdGUgdXJsIGNvbnRhaW5zIGxvY2FsZSBwbGFjZWhvbGRlcicsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiDop6PmnpDnv7vor5HmlofmnKxcbiAgICovXG4gIHByaXZhdGUgcmVzb2x2ZVRyYW5zbGF0aW9uKGtleTogc3RyaW5nLCBsb2NhbGUgPSB0aGlzLmxvY2FsZSk6IHN0cmluZyB7XG4gICAgLy8g5LyY5YWI5LuO6L+c56iL57+76K+R5Lit5p+l5om+XG4gICAgbGV0IHZhbHVlID0gdGhpcy5zZWFyY2hJblRyYW5zbGF0aW9uc0xpc3QoXG4gICAgICBrZXksXG4gICAgICBsb2NhbGUsXG4gICAgICB0aGlzLnJlbW90ZVRyYW5zbGF0aW9uc0xpc3QsXG4gICAgKTtcblxuICAgIC8vIOWmguaenOi/nOeoi+e/u+ivkeS4reayoeacieaJvuWIsO+8iHVuZGVmaW5lZO+8ie+8jOWImeS7juacrOWcsOe/u+ivkeS4reafpeaJvlxuICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB2YWx1ZSA9IHRoaXMuc2VhcmNoSW5UcmFuc2xhdGlvbnNMaXN0KGtleSwgbG9jYWxlLCB0aGlzLnRyYW5zbGF0aW9uc0xpc3QpO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZSA/PyBrZXk7XG4gIH1cblxuICAvKipcbiAgICog5Zyo57+76K+R5YiX6KGo5Lit5pCc57SiXG4gICAqL1xuICBwcml2YXRlIHNlYXJjaEluVHJhbnNsYXRpb25zTGlzdChcbiAgICBrZXk6IHN0cmluZyxcbiAgICBsb2NhbGU6IHN0cmluZyxcbiAgICB0cmFuc2xhdGlvbnNMaXN0OiBUcmFuc2xhdGlvbnNbXSxcbiAgKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIXRyYW5zbGF0aW9uc0xpc3QgfHwgdHJhbnNsYXRpb25zTGlzdC5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLy8g5LuO5ZCO5b6A5YmN6YGN5Y6G77yI5ZCO5Yqg5YWl55qE5LyY5YWI57qn5pu06auY77yJXG4gICAgZm9yIChsZXQgaSA9IHRyYW5zbGF0aW9uc0xpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5zZWFyY2hJblRyYW5zbGF0aW9ucyhrZXksIGxvY2FsZSwgdHJhbnNsYXRpb25zTGlzdFtpXSk7XG4gICAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiDlnKjljZXkuKrnv7vor5Hlr7nosaHkuK3mkJzntKJcbiAgICovXG4gIHByaXZhdGUgc2VhcmNoSW5UcmFuc2xhdGlvbnMoXG4gICAga2V5OiBzdHJpbmcsXG4gICAgbG9jYWxlOiBzdHJpbmcsXG4gICAgdHJhbnNsYXRpb25zOiBUcmFuc2xhdGlvbnMsXG4gICk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgdHJhbnNsYXRpb25WYWx1ZSA9IHRoaXMuZ2V0VHJhbnNsYXRpb25WYWx1ZSh0cmFuc2xhdGlvbnMsIGxvY2FsZSk7XG5cbiAgICAvLyDlpoLmnpzmsqHmnInojrflj5bliLDnv7vor5HlgLzlr7nosaHvvIhnZXRUcmFuc2xhdGlvblZhbHVl5bey57uP5aSE55CG5LqGbG9vc2XlkoxmYWxsYmFja++8ie+8jOebtOaOpei/lOWbnlxuICAgIGlmICh0cmFuc2xhdGlvblZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLy8g6I635Y+W57+76K+R5YC877yM5pSv5oyB5omB5bmz5ZKM5bWM5aWX5Lik56eN57uT5p6EXG4gICAgY29uc3QgdmFsdWUgPSB0aGlzLmdldFRyYW5zbGF0aW9uRnJvbVNvdXJjZSh0cmFuc2xhdGlvblZhbHVlLCBrZXkpO1xuXG4gICAgLy8g5aaC5p6c5om+5Yiw5YC877yI5YyF5ousbnVsbOWAvO+8ie+8jOWImeWkhOeQhuW5tui/lOWbnlxuICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLnZhbGlkYXRlVHJhbnNsYXRpb25WYWx1ZSh2YWx1ZSwgbG9jYWxlLCBrZXkpO1xuICAgICAgLy8gbnVsbOWAvOi9rOaNouS4uuWtl+espuS4sidudWxsJ++8jOWFtuS7luWAvOato+W4uOi9rOaNolxuICAgICAgcmV0dXJuIHZhbHVlID09PSBudWxsID8gJ251bGwnIDogU3RyaW5nKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvLyDlpoLmnpzlnKjlvZPliY3or63oqIDnmoTnv7vor5HlgLzkuK3mib7kuI3liLBrZXnvvIzkvYbov5nkuI3mmK9mYWxsYmFja+ivreiogO+8jOWwneivlWZhbGxiYWNrXG4gICAgaWYgKGxvY2FsZSAhPT0gdGhpcy5vcHRpb25zLmZhbGxiYWNrTG9jYWxlKSB7XG4gICAgICBjb25zdCBmYWxsYmFja1RyYW5zbGF0aW9uVmFsdWUgPSB0aGlzLmdldFRyYW5zbGF0aW9uVmFsdWUoXG4gICAgICAgIHRyYW5zbGF0aW9ucyxcbiAgICAgICAgdGhpcy5vcHRpb25zLmZhbGxiYWNrTG9jYWxlLFxuICAgICAgKTtcblxuICAgICAgaWYgKGZhbGxiYWNrVHJhbnNsYXRpb25WYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGNvbnN0IGZhbGxiYWNrVmFsdWUgPSB0aGlzLmdldFRyYW5zbGF0aW9uRnJvbVNvdXJjZShcbiAgICAgICAgICBmYWxsYmFja1RyYW5zbGF0aW9uVmFsdWUsXG4gICAgICAgICAga2V5LFxuICAgICAgICApO1xuICAgICAgICBpZiAoZmFsbGJhY2tWYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhpcy52YWxpZGF0ZVRyYW5zbGF0aW9uVmFsdWUoXG4gICAgICAgICAgICBmYWxsYmFja1ZhbHVlLFxuICAgICAgICAgICAgdGhpcy5vcHRpb25zLmZhbGxiYWNrTG9jYWxlLFxuICAgICAgICAgICAga2V5LFxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuIGZhbGxiYWNrVmFsdWUgPT09IG51bGwgPyAnbnVsbCcgOiBTdHJpbmcoZmFsbGJhY2tWYWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIOS7jue/u+ivkea6kOiOt+WPlue/u+ivkeWAvO+8jOaUr+aMgeaJgeW5s+WSjOW1jOWll+S4pOenjee7k+aehFxuICAgKiBAcGFyYW0gc291cmNlIC0g57+76K+R5rqQ5a+56LGhXG4gICAqIEBwYXJhbSBrZXkgLSDnv7vor5HplK7vvIjlpoIgJ2EuYi5jJ++8iVxuICAgKiBAcmV0dXJucyDnv7vor5HlgLzmiJZ1bmRlZmluZWRcbiAgICovXG4gIHByaXZhdGUgZ2V0VHJhbnNsYXRpb25Gcm9tU291cmNlKHNvdXJjZTogYW55LCBrZXk6IHN0cmluZyk6IGFueSB7XG4gICAgaWYgKCFzb3VyY2UgfHwgdHlwZW9mIHNvdXJjZSAhPT0gJ29iamVjdCcpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLy8gMS4g5LyY5YWI5bCd6K+V5omB5bmz57uT5p6E77ya55u05o6l5p+l5om+5a6M5pW055qE6ZSuICdhLmIuYydcbiAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHNvdXJjZSwga2V5KSkge1xuICAgICAgcmV0dXJuIHNvdXJjZVtrZXldO1xuICAgIH1cblxuICAgIC8vIDIuIOWGjeWwneivleW1jOWll+e7k+aehO+8muS9v+eUqGxvZGFzaC5nZXTmjInot6/lvoTmn6Xmib4gYS5iLmNcbiAgICBjb25zdCBuZXN0ZWRWYWx1ZSA9IGdldChzb3VyY2UsIGtleSk7XG4gICAgaWYgKG5lc3RlZFZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBuZXN0ZWRWYWx1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIOiOt+WPluaMh+WumuivreiogOeahOe/u+ivkeWAvO+8iOWkhOeQhmxvb3Nl5qih5byP5ZKMZmFsbGJhY2vpgLvovpHvvIlcbiAgICovXG4gIHByaXZhdGUgZ2V0VHJhbnNsYXRpb25WYWx1ZShcbiAgICBzb3VyY2U6IFRyYW5zbGF0aW9uLFxuICAgIGxvY2FsZSA9IHRoaXMubG9jYWxlLFxuICApOiBUcmFuc2xhdGlvblZhbHVlIHtcbiAgICBpZiAoIXNvdXJjZSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvLyAxLiDpppblhYjmo4Dmn6Xnsr7noa7ljLnphY3nmoTplK7mmK/lkKblrZjlnKhcbiAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHNvdXJjZSwgbG9jYWxlKSkge1xuICAgICAgcmV0dXJuIHNvdXJjZVtsb2NhbGVdOyAvLyDov5Tlm57lrp7pmYXlgLzvvIzlj6/og73mmK9udWxs44CBdW5kZWZpbmVk5oiW5YW25LuW5YC8XG4gICAgfVxuXG4gICAgLy8gMi4g5aaC5p6c5ZCv55So5LqG5a695p2+5qih5byP77yM5bCd6K+V5a695p2+5Yy56YWNXG4gICAgaWYgKHRoaXMub3B0aW9ucy5sb29zZSkge1xuICAgICAgY29uc3QgbG9vc2VWYWx1ZSA9IHRoaXMuZ2V0TG9vc2VUcmFuc2xhdGlvblZhbHVlKHNvdXJjZSwgbG9jYWxlKTtcbiAgICAgIGlmIChsb29zZVZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIGxvb3NlVmFsdWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gMy4g5aaC5p6c5b2T5YmN6K+t6KiA5LiN5pivZmFsbGJhY2vor63oqIDvvIzlsJ3or5VmYWxsYmFja+ivreiogFxuICAgIGlmIChsb2NhbGUgIT09IHRoaXMub3B0aW9ucy5mYWxsYmFja0xvY2FsZSkge1xuICAgICAgLy8g6aaW5YWI5qOA5p+lZmFsbGJhY2vor63oqIDnmoTnsr7noa7ljLnphY1cbiAgICAgIGlmIChcbiAgICAgICAgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKFxuICAgICAgICAgIHNvdXJjZSxcbiAgICAgICAgICB0aGlzLm9wdGlvbnMuZmFsbGJhY2tMb2NhbGUsXG4gICAgICAgIClcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gc291cmNlW3RoaXMub3B0aW9ucy5mYWxsYmFja0xvY2FsZV07XG4gICAgICB9XG5cbiAgICAgIC8vIOWmguaenOWQr+eUqOS6huWuveadvuaooeW8j++8jOS5n+WvuWZhbGxiYWNr6K+t6KiA6L+b6KGM5a695p2+5Yy56YWNXG4gICAgICBpZiAodGhpcy5vcHRpb25zLmxvb3NlKSB7XG4gICAgICAgIGNvbnN0IGZhbGxiYWNrTG9vc2VWYWx1ZSA9IHRoaXMuZ2V0TG9vc2VUcmFuc2xhdGlvblZhbHVlKFxuICAgICAgICAgIHNvdXJjZSxcbiAgICAgICAgICB0aGlzLm9wdGlvbnMuZmFsbGJhY2tMb2NhbGUsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChmYWxsYmFja0xvb3NlVmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHJldHVybiBmYWxsYmFja0xvb3NlVmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIOWuveadvuaooeW8j+S4i+iOt+WPlue/u+ivkeWAvFxuICAgKi9cbiAgcHJpdmF0ZSBnZXRMb29zZVRyYW5zbGF0aW9uVmFsdWUoXG4gICAgc291cmNlOiBUcmFuc2xhdGlvbixcbiAgICBsb2NhbGU6IHN0cmluZyxcbiAgKTogVHJhbnNsYXRpb25WYWx1ZSB7XG4gICAgY29uc3QgbG9vc2VMb2NhbGUgPSB0aGlzLmV4dHJhY3RMb29zZUxvY2FsZShsb2NhbGUpO1xuXG4gICAgaWYgKGxvY2FsZSA9PT0gbG9vc2VMb2NhbGUpIHtcbiAgICAgIC8vIOWvu+aJvuWMuemFjeeahOWuveadvuivreiogFxuICAgICAgY29uc3QgbWF0Y2hlZEVudHJ5ID0gT2JqZWN0LmVudHJpZXMoc291cmNlKS5maW5kKFxuICAgICAgICAoW2tleV0pID0+IGxvb3NlTG9jYWxlID09PSB0aGlzLmV4dHJhY3RMb29zZUxvY2FsZShrZXkpLFxuICAgICAgKTtcbiAgICAgIHJldHVybiBtYXRjaGVkRW50cnk/LlsxXTtcbiAgICB9XG5cbiAgICAvLyDmo4Dmn6Xlrr3mnb7or63oqIDplK7mmK/lkKblrZjlnKhcbiAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHNvdXJjZSwgbG9vc2VMb2NhbGUpKSB7XG4gICAgICByZXR1cm4gc291cmNlW2xvb3NlTG9jYWxlXTtcbiAgICB9XG5cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIOaPkOWPluWuveadvuivreiogOS7o+egge+8iOWmgu+8mnpoLUNOIC0+IHpo77yJXG4gICAqL1xuICBwcml2YXRlIGV4dHJhY3RMb29zZUxvY2FsZShsb2NhbGU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGhlYWQobG9jYWxlLnNwbGl0KC9bXy1dLykpIHx8IGxvY2FsZTtcbiAgfVxuXG4gIC8qKlxuICAgKiDpqozor4Hnv7vor5HlgLzvvIjlvIDlj5HmqKHlvI/vvIlcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVUcmFuc2xhdGlvblZhbHVlKFxuICAgIHZhbHVlOiBhbnksXG4gICAgbG9jYWxlOiBzdHJpbmcsXG4gICAga2V5OiBzdHJpbmcsXG4gICk6IHZvaWQge1xuICAgIGlmIChcbiAgICAgIGlzRGV2TW9kZSgpICYmXG4gICAgICB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmXG4gICAgICB0eXBlb2YgZ2V0KHZhbHVlLCBTeW1ib2wudG9QcmltaXRpdmUpICE9PSAnZnVuY3Rpb24nXG4gICAgKSB7XG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIGBUaGUgdHJhbnNsYXRpb24gZm9yIGxvY2FsZTogXFxgJHtsb2NhbGV9XFxgIGFuZCBrZXk6XFxgJHtrZXl9XFxgIGlzIGFuIG9iamVjdCwgd2hpY2ggY291bGQgYmUgdW5leHBlY3RlZGAsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiDmr5TovoPnv7vor5HplK7vvIjlvIDlj5HmqKHlvI/kuIvmo4Dmn6Xph43lpI3vvIlcbiAgICovXG4gIHByaXZhdGUgY29tcGFyZVRyYW5zbGF0aW9uS2V5cyhcbiAgICBsb2NhbGU6IHN0cmluZyxcbiAgICB0cmFuc2xhdGlvbjogVHJhbnNsYXRpb24sXG4gICAgcHJldlRyYW5zbGF0aW9uOiBUcmFuc2xhdGlvbixcbiAgICBwYXRoOiBzdHJpbmdbXSA9IFtdLFxuICApOiB2b2lkIHtcbiAgICBpZiAodHJhbnNsYXRpb24gPT0gbnVsbCB8fCBwcmV2VHJhbnNsYXRpb24gPT0gbnVsbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIE9iamVjdC5lbnRyaWVzKHRyYW5zbGF0aW9uKS5mb3JFYWNoKChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICAgIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHByZXZUcmFuc2xhdGlvbiwga2V5KSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHByZXZWYWx1ZSA9IHByZXZUcmFuc2xhdGlvbltrZXldO1xuICAgICAgY29uc3QgdmFsdWVJc1BsYWluT2JqZWN0ID0gaXNQbGFpbk9iamVjdCh2YWx1ZSk7XG4gICAgICBjb25zdCBwcmV2VmFsdWVJc1BsYWluT2JqZWN0ID0gaXNQbGFpbk9iamVjdChwcmV2VmFsdWUpO1xuXG4gICAgICBpZiAodmFsdWVJc1BsYWluT2JqZWN0ICYmIHByZXZWYWx1ZUlzUGxhaW5PYmplY3QpIHtcbiAgICAgICAgdGhpcy5jb21wYXJlVHJhbnNsYXRpb25LZXlzKFxuICAgICAgICAgIGxvY2FsZSxcbiAgICAgICAgICB2YWx1ZSBhcyBUcmFuc2xhdGlvbixcbiAgICAgICAgICBwcmV2VmFsdWUgYXMgVHJhbnNsYXRpb24sXG4gICAgICAgICAgWy4uLnBhdGgsIGtleV0sXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKCF2YWx1ZUlzUGxhaW5PYmplY3QgJiYgIXByZXZWYWx1ZUlzUGxhaW5PYmplY3QpIHtcbiAgICAgICAgY29uc3Qgb3V0cHV0UGF0aCA9IFsuLi5wYXRoLCBrZXldLmpvaW4oJyAtPiAnKTtcbiAgICAgICAgaWYgKHZhbHVlID09PSBwcmV2VmFsdWUpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICBgVGhlIGN1c3RvbWl6ZWQgdHJhbnNsYXRpb24gZm9yIGxvY2FsZTogXFxgJHtsb2NhbGV9XFxgIGFuZCBwYXRoOiBcXGAke291dHB1dFBhdGh9XFxgIGlzIGR1cGxpY2F0ZWQgd2l0aCB0aGUgb3RoZXIgdHJhbnNsYXRpb24sIHBsZWFzZSByZW1vdmUgaXQgaW4geW91ciB0cmFuc2xhdGlvbiBmaWxlLmAsXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICBgVHdvIGtleXMgdGhhdCB0aGUgbG9jYWxlIGlzIFxcYCR7bG9jYWxlfVxcYCBhbmQgdGhlIHBhdGggaXMgXFxgJHtvdXRwdXRQYXRofVxcYCBhcmUgc2FtZSwgYnV0IHRoZWlyIHZhbHVlcyBhcmUgbm90IGVxdWFsLCBwbGVhc2UgcmVtb3ZlIG9uZSBvZiB0aGVtIG9yIGNoYW5nZSBvbmUgb2YgdGhlIGtleXMuYCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==