@infrab4a/connect-angular 4.10.0-beta.10 → 4.10.0-beta.12

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 (112) hide show
  1. package/angular-connect.module.d.ts +27 -29
  2. package/angular-elastic-search.module.d.ts +9 -9
  3. package/angular-firebase-auth.module.d.ts +11 -11
  4. package/angular-firestore.module.d.ts +17 -17
  5. package/angular-hasura-graphql.module.d.ts +16 -16
  6. package/consts/backend-url.const.d.ts +1 -1
  7. package/consts/category-structure.d.ts +1 -1
  8. package/consts/default-shop.const.d.ts +1 -1
  9. package/consts/es-config.const.d.ts +1 -1
  10. package/consts/firebase-const.d.ts +3 -3
  11. package/consts/hasura-options.const.d.ts +1 -1
  12. package/consts/index.d.ts +7 -8
  13. package/consts/persistence.const.d.ts +1 -1
  14. package/consts/storage-base-url.const.d.ts +1 -1
  15. package/esm2020/angular-connect.module.mjs +133 -146
  16. package/esm2020/angular-elastic-search.module.mjs +34 -34
  17. package/esm2020/angular-firebase-auth.module.mjs +115 -115
  18. package/esm2020/angular-firestore.module.mjs +499 -499
  19. package/esm2020/angular-hasura-graphql.module.mjs +287 -287
  20. package/esm2020/consts/backend-url.const.mjs +1 -1
  21. package/esm2020/consts/category-structure.mjs +2 -2
  22. package/esm2020/consts/default-shop.const.mjs +2 -2
  23. package/esm2020/consts/es-config.const.mjs +2 -2
  24. package/esm2020/consts/firebase-const.mjs +4 -4
  25. package/esm2020/consts/hasura-options.const.mjs +2 -2
  26. package/esm2020/consts/index.mjs +8 -9
  27. package/esm2020/consts/persistence.const.mjs +2 -2
  28. package/esm2020/consts/storage-base-url.const.mjs +2 -2
  29. package/esm2020/helpers/index.mjs +2 -2
  30. package/esm2020/helpers/mobile-operation-system-checker.helper.mjs +7 -7
  31. package/esm2020/index.mjs +7 -7
  32. package/esm2020/infrab4a-connect-angular.mjs +4 -4
  33. package/esm2020/persistence/cookie-data-persistence.mjs +22 -22
  34. package/esm2020/persistence/data-persistence.mjs +2 -2
  35. package/esm2020/persistence/index.mjs +3 -3
  36. package/esm2020/services/auth.service.mjs +37 -37
  37. package/esm2020/services/cart.service.mjs +284 -282
  38. package/esm2020/services/catalog/adapters/category-structure.adapter.mjs +2 -2
  39. package/esm2020/services/catalog/adapters/index.mjs +4 -4
  40. package/esm2020/services/catalog/adapters/new-category-structure.adapter.mjs +43 -43
  41. package/esm2020/services/catalog/adapters/old-category-structure.adapter.mjs +23 -23
  42. package/esm2020/services/catalog/catalog.service.mjs +235 -274
  43. package/esm2020/services/catalog/category.service.mjs +51 -51
  44. package/esm2020/services/catalog/enums/index.mjs +2 -2
  45. package/esm2020/services/catalog/enums/product-sorts.enum.mjs +11 -11
  46. package/esm2020/services/catalog/index.mjs +8 -8
  47. package/esm2020/services/catalog/models/category-with-tree.model.mjs +10 -10
  48. package/esm2020/services/catalog/models/index.mjs +2 -2
  49. package/esm2020/services/catalog/types/index.mjs +2 -2
  50. package/esm2020/services/catalog/types/product-sort.type.mjs +2 -2
  51. package/esm2020/services/catalog/wishlist.service.mjs +129 -133
  52. package/esm2020/services/checkout-subscription.service.mjs +50 -50
  53. package/esm2020/services/checkout.service.mjs +68 -68
  54. package/esm2020/services/coupon.service.mjs +265 -260
  55. package/esm2020/services/helpers/index.mjs +2 -2
  56. package/esm2020/services/helpers/util.helper.mjs +18 -18
  57. package/esm2020/services/home-shop.service.mjs +125 -125
  58. package/esm2020/services/index.mjs +11 -11
  59. package/esm2020/services/order.service.mjs +30 -30
  60. package/esm2020/services/shipping.service.mjs +96 -96
  61. package/esm2020/services/types/index.mjs +3 -3
  62. package/esm2020/services/types/required-checkout-data.type.mjs +2 -2
  63. package/esm2020/services/types/required-checkout-subscription-data.type.mjs +2 -2
  64. package/esm2020/services/types/shipping-methods.type.mjs +2 -2
  65. package/esm2020/types/firebase-app-config.type.mjs +2 -2
  66. package/esm2020/types/index.mjs +2 -2
  67. package/fesm2015/infrab4a-connect-angular.mjs +2449 -2529
  68. package/fesm2015/infrab4a-connect-angular.mjs.map +1 -1
  69. package/fesm2020/infrab4a-connect-angular.mjs +2393 -2473
  70. package/fesm2020/infrab4a-connect-angular.mjs.map +1 -1
  71. package/helpers/index.d.ts +1 -1
  72. package/helpers/mobile-operation-system-checker.helper.d.ts +3 -3
  73. package/index.d.ts +6 -6
  74. package/package.json +2 -2
  75. package/persistence/cookie-data-persistence.d.ts +10 -10
  76. package/persistence/data-persistence.d.ts +6 -6
  77. package/persistence/index.d.ts +2 -2
  78. package/services/auth.service.d.ts +18 -18
  79. package/services/cart.service.d.ts +42 -42
  80. package/services/catalog/adapters/category-structure.adapter.d.ts +4 -4
  81. package/services/catalog/adapters/index.d.ts +3 -3
  82. package/services/catalog/adapters/new-category-structure.adapter.d.ts +12 -12
  83. package/services/catalog/adapters/old-category-structure.adapter.d.ts +10 -10
  84. package/services/catalog/catalog.service.d.ts +89 -89
  85. package/services/catalog/category.service.d.ts +20 -20
  86. package/services/catalog/enums/index.d.ts +1 -1
  87. package/services/catalog/enums/product-sorts.enum.d.ts +9 -9
  88. package/services/catalog/index.d.ts +7 -7
  89. package/services/catalog/models/category-with-tree.model.d.ts +4 -4
  90. package/services/catalog/models/index.d.ts +1 -1
  91. package/services/catalog/types/index.d.ts +1 -1
  92. package/services/catalog/types/product-sort.type.d.ts +2 -2
  93. package/services/catalog/wishlist.service.d.ts +44 -45
  94. package/services/checkout-subscription.service.d.ts +19 -19
  95. package/services/checkout.service.d.ts +27 -27
  96. package/services/coupon.service.d.ts +33 -33
  97. package/services/helpers/index.d.ts +1 -1
  98. package/services/helpers/util.helper.d.ts +3 -3
  99. package/services/home-shop.service.d.ts +26 -26
  100. package/services/index.d.ts +10 -10
  101. package/services/order.service.d.ts +13 -13
  102. package/services/shipping.service.d.ts +19 -19
  103. package/services/types/index.d.ts +2 -2
  104. package/services/types/required-checkout-data.type.d.ts +2 -2
  105. package/services/types/required-checkout-subscription-data.type.d.ts +2 -2
  106. package/services/types/shipping-methods.type.d.ts +12 -12
  107. package/types/firebase-app-config.type.d.ts +1 -1
  108. package/types/index.d.ts +1 -1
  109. package/angular-vertex-search.module.d.ts +0 -9
  110. package/consts/vertex-config.const.d.ts +0 -1
  111. package/esm2020/angular-vertex-search.module.mjs +0 -34
  112. package/esm2020/consts/vertex-config.const.mjs +0 -2
@@ -1,274 +1,235 @@
1
- import { Inject, Injectable } from '@angular/core';
2
- import { InvalidArgumentError, RoundProductPricesHelper, set, Shops, Where, } from '@infrab4a/connect';
3
- import { CATEGORY_STRUCTURE, DEFAULT_SHOP } from '../../consts';
4
- import * as i0 from "@angular/core";
5
- import * as i1 from "@infrab4a/connect";
6
- export class CatalogService {
7
- constructor(productRepository, productStockNotificationRepository, categoryRepository, categoryStructureAdapter, shop, productSearch) {
8
- this.productRepository = productRepository;
9
- this.productStockNotificationRepository = productStockNotificationRepository;
10
- this.categoryRepository = categoryRepository;
11
- this.categoryStructureAdapter = categoryStructureAdapter;
12
- this.shop = shop;
13
- this.productSearch = productSearch;
14
- this.productsByTerm = {};
15
- this.buildFilterQuery = ({ clubDiscount, brands, prices, gender, tags, rate, customOptions, }) => {
16
- const filters = {};
17
- if (clubDiscount?.length)
18
- set(filters, 'price.subscriberDiscountPercentage', { operator: Where.IN, value: clubDiscount });
19
- if (brands?.length)
20
- filters.brand = { operator: Where.IN, value: brands };
21
- if (gender?.length)
22
- filters.gender = { operator: Where.IN, value: gender };
23
- if (prices?.min || prices?.max)
24
- set(filters, prices.subscriberPrice ? 'price.subscriberPrice' : 'price.price', [
25
- ...(prices.min ? [{ operator: Where.GTE, value: Math.round(prices.min) }] : []),
26
- ...(prices.max ? [{ operator: Where.LTE, value: Math.ceil(prices.max) }] : []),
27
- ]);
28
- if (rate)
29
- filters.rate = { operator: Where.GTE, value: rate };
30
- if (tags?.length)
31
- filters.tags = { operator: Where.LIKE, value: tags };
32
- if (customOptions?.length)
33
- filters.filters = { operator: Where.LIKE, value: customOptions };
34
- return filters;
35
- };
36
- this.buildSortQuery = (sort) => {
37
- if (!sort || sort === 'most-relevant')
38
- return {};
39
- if (sort === 'best-sellers')
40
- return {
41
- shoppingCount: 'desc',
42
- rate: 'desc',
43
- stock: 'desc',
44
- name: 'asc',
45
- };
46
- if (sort === 'biggest-price')
47
- return { subscriberPrice: 'desc', rate: 'desc', shoppingCount: 'desc' };
48
- if (sort === 'lowest-price')
49
- return { subscriberPrice: 'asc', rate: 'desc', shoppingCount: 'desc' };
50
- if (sort === 'best-rating')
51
- return { rate: 'desc', shoppingCount: 'desc', stock: 'desc', name: 'asc' };
52
- if (sort === 'news')
53
- return { createdAt: 'desc' };
54
- if (sort === 'biggest-discount')
55
- return { subscriberDiscountPercentage: 'desc', rate: 'desc', shoppingCount: 'desc' };
56
- };
57
- this.buildLimitQuery = (options) => {
58
- const limit = options?.perPage || 20;
59
- return {
60
- limit,
61
- offset: ((options?.page || 1) - 1) * limit,
62
- };
63
- };
64
- this.hasProfile = (options) => 'profile' in options;
65
- this.hasTerm = (options) => 'term' in options;
66
- this.hasCategory = (options) => 'category' in options;
67
- }
68
- async fetchProducts(options) {
69
- const limits = this.buildLimitQuery(options);
70
- if (this.hasProfile(options) && options.filters?.customOptions)
71
- throw new InvalidArgumentError(`It couldn't filled customOptions when profile is given`);
72
- if (this.hasProfile(options) && options.filters?.tags)
73
- throw new InvalidArgumentError(`It couldn't filled tags when profile is given`);
74
- if (this.hasTerm(options) && options.filters?.customOptions)
75
- throw new InvalidArgumentError(`It couldn't filled customOptions when term is given`);
76
- console.log('fetchProducts', options);
77
- return await this.findCatalog(options, limits).then(({ data, count: total, maximum, minimal, distinct }) => ({
78
- products: { data: data.map((product) => RoundProductPricesHelper.roundProductPrices(product)), total },
79
- pages: Math.ceil(total / limits.limit),
80
- prices: {
81
- price: { min: +minimal?.price?.price?.toFixed(2), max: +maximum?.price?.price?.toFixed(2) },
82
- subscriberPrice: {
83
- min: +minimal?.price?.subscriberPrice?.toFixed(2),
84
- max: +maximum?.price?.subscriberPrice?.toFixed(2),
85
- },
86
- },
87
- brands: distinct?.brand,
88
- }));
89
- }
90
- async addCustomerToStockNotification(shop, productId, name, email) {
91
- return this.productStockNotificationRepository.addCustomerEmail(shop, productId, name, email);
92
- }
93
- async findCatalog(options, limits) {
94
- if (this.hasTerm(options) && options.sort === 'most-relevant') {
95
- // console.log('Step 1')
96
- const productsIds = await this.findCatalogIdsBySearch(options.term);
97
- return this.findCatalogAndSortByMostRevelantByTerm(productsIds, options, limits);
98
- }
99
- if (this.hasCategory(options) && options.sort === 'most-relevant') {
100
- const mostRelevant = options.category.isWishlist ? [] : options.category.getMostRelevantByShop(this.shop);
101
- const productsIds = await this.productRepository
102
- .findCatalog({
103
- fields: ['id'],
104
- filters: {
105
- ...(await this.buildMainFilter(options)),
106
- ...this.buildFilterQuery(options?.filters || {}),
107
- },
108
- })
109
- .then((products) => products.data.map((product) => product.id));
110
- return this.findCatalogAndSortByMostRevelant(mostRelevant, productsIds, options, limits);
111
- }
112
- const repoParams = {
113
- filters: {
114
- ...(await this.buildMainFilter(options)),
115
- ...this.buildFilterQuery(options?.filters || {}),
116
- },
117
- ...(options?.sort ? { orderBy: this.buildSortQuery(options?.sort) } : {}),
118
- limits,
119
- options: {
120
- minimal: ['price'],
121
- maximum: ['price'],
122
- ...(!this.hasCategory(options) ? { distinct: ['brand'] } : {}),
123
- },
124
- };
125
- if (['biggest-price', 'lowest-price', 'biggest-discount', 'best-rating'].includes(options.sort))
126
- return this.productRepository.findCatalog(repoParams);
127
- return this.productRepository.findCatalog(repoParams, options?.mainGender || this.shop === Shops.MENSMARKET ? 'male' : 'female');
128
- }
129
- async buildMainFilter({ category, profile, term, }) {
130
- if (category)
131
- return this.categoryStructureAdapter.buildProductFilterByCategory(category);
132
- if (profile)
133
- return { tags: { operator: Where.LIKE, value: profile } };
134
- if (term)
135
- return this.productSearch
136
- .search(term, 999, this.shop == Shops.GLAMSHOP ? 'female' : 'male')
137
- .then((data) => ({ id: { operator: Where.IN, value: data.map((_source) => _source.id) } }));
138
- }
139
- async findCatalogAndSortByMostRevelant(mostRelevants, productIds, options, limits) {
140
- const mostRelevantProductsIds = [...new Set(mostRelevants.concat(productIds))];
141
- const totalResult = await this.productRepository.findCatalog({
142
- filters: {
143
- id: { operator: Where.IN, value: mostRelevantProductsIds },
144
- ...this.buildFilterQuery(options?.filters || {}),
145
- },
146
- orderBy: this.buildSortQuery('best-sellers'),
147
- options: {
148
- minimal: ['price'],
149
- maximum: ['price'],
150
- distinct: ['brand'],
151
- },
152
- }, options?.mainGender || this.shop === Shops.MENSMARKET ? 'male' : 'female');
153
- const mostRelevantWithouyStock = totalResult.data.filter((product) => mostRelevants.includes(product.id) && product.stock.quantity <= 0);
154
- const firstProducts = totalResult.data
155
- .filter((product) => mostRelevants.includes(product.id) && product.stock.quantity > 0)
156
- .sort((a, b) => mostRelevants.indexOf(a.id) - mostRelevants.indexOf(b.id));
157
- const lastProducts = totalResult.data
158
- .filter((product) => !mostRelevants.includes(product.id))
159
- .concat(mostRelevantWithouyStock);
160
- const categoryMostRelevants = firstProducts.concat(lastProducts);
161
- const resultFinal = categoryMostRelevants.slice(limits.offset, limits.offset + limits.limit);
162
- return {
163
- data: resultFinal,
164
- count: totalResult.count,
165
- maximum: totalResult.maximum,
166
- minimal: totalResult.minimal,
167
- distinct: totalResult.distinct,
168
- };
169
- }
170
- async findCatalogAndSortByMostRevelantByTerm(productIds, options, limits) {
171
- // console.log('findCatalogAndSortByMostRevelantByTerm', this.shop, options, limits)
172
- // console.log(
173
- // 'productIds from search',
174
- // productIds.length,
175
- // 'preview -> ',
176
- // productIds.slice(limits.offset, limits.offset + limits.limit),
177
- // )
178
- const totalResult = await this.productRepository.findCatalog({
179
- fields: ['id', 'stock', 'gender'],
180
- filters: {
181
- id: { operator: Where.IN, value: productIds },
182
- published: { operator: Where.EQUALS, value: true },
183
- ...this.buildFilterQuery(options?.filters || {}),
184
- },
185
- options: {
186
- minimal: ['price'],
187
- maximum: ['price'],
188
- distinct: ['brand'],
189
- },
190
- }, options?.mainGender || this.shop === Shops.MENSMARKET ? 'male' : 'female');
191
- // const productsTotalResult = totalResult.data.slice(limits.offset, limits.offset + limits.limit)
192
- // console.log(
193
- // 'productsTotalResult',
194
- // productsTotalResult.map((p) => {
195
- // return {
196
- // id: p.id,
197
- // stock: p.stock.quantity,
198
- // }
199
- // }),
200
- // )
201
- const defaultGender = options?.filters?.gender
202
- ? options?.filters?.gender.at(0)
203
- : this.shop === Shops.GLAMSHOP
204
- ? 'female'
205
- : 'male';
206
- const stockData = totalResult.data.filter((product) => product.stock.quantity > 0);
207
- const stockOut = totalResult.data.filter((product) => product.stock.quantity <= 0);
208
- const productIdsStockGender = productIds.filter((product) => stockData.some((result) => result.id === product && (result.gender?.includes(defaultGender) || result.gender?.includes('unisex'))));
209
- const productIdsStockNotGender = productIds.filter((product) => stockData.some((result) => result.id === product && !result.gender?.includes(defaultGender) && !result.gender?.includes('unisex')));
210
- const productIdsStock = productIdsStockGender.concat(productIdsStockNotGender);
211
- const productIdsStockOut = productIds.filter((product) => stockOut.some((result) => result.id === product));
212
- const limitedProductId = productIdsStock
213
- .concat(productIdsStockOut)
214
- .slice(limits.offset, limits.offset + limits.limit);
215
- // console.log('limitedProductId', limitedProductId)
216
- const orderedId = productIds.filter((product) => limitedProductId.includes(product));
217
- const productResult = await this.productRepository.findCatalog({
218
- filters: {
219
- id: { operator: Where.IN, value: orderedId },
220
- },
221
- });
222
- const finalResult = limitedProductId
223
- .map((id) => productResult.data.find((product) => product.id === id))
224
- .filter(Boolean);
225
- // console.log(
226
- // 'finalResult',
227
- // finalResult.map((p) => {
228
- // return {
229
- // id: p.id,
230
- // name: p.name,
231
- // brand: p.brand,
232
- // }
233
- // }),
234
- // )
235
- return {
236
- data: limitedProductId.map((id) => productResult.data.find((product) => product.id === id)).filter(Boolean),
237
- count: totalResult.count,
238
- maximum: totalResult.maximum,
239
- minimal: totalResult.minimal,
240
- distinct: totalResult.distinct,
241
- };
242
- }
243
- async findCatalogIdsBySearch(term, preview = false) {
244
- if (this.productsByTerm[term])
245
- return this.productsByTerm[term];
246
- return (this.productsByTerm[term] = await this.productSearch
247
- .search(term, 999, this.shop == Shops.GLAMSHOP ? 'female' : 'male')
248
- .then((products) => [...new Set(products.map((product) => product.id))]));
249
- }
250
- }
251
- CatalogService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.0", ngImport: i0, type: CatalogService, deps: [{ token: 'ProductRepository' }, { token: 'ProductStockNotificationRepository' }, { token: 'CategoryRepository' }, { token: CATEGORY_STRUCTURE }, { token: DEFAULT_SHOP }, { token: 'ProductSearch' }], target: i0.ɵɵFactoryTarget.Injectable });
252
- CatalogService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.1.0", ngImport: i0, type: CatalogService });
253
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.0", ngImport: i0, type: CatalogService, decorators: [{
254
- type: Injectable
255
- }], ctorParameters: function () { return [{ type: undefined, decorators: [{
256
- type: Inject,
257
- args: ['ProductRepository']
258
- }] }, { type: undefined, decorators: [{
259
- type: Inject,
260
- args: ['ProductStockNotificationRepository']
261
- }] }, { type: undefined, decorators: [{
262
- type: Inject,
263
- args: ['CategoryRepository']
264
- }] }, { type: undefined, decorators: [{
265
- type: Inject,
266
- args: [CATEGORY_STRUCTURE]
267
- }] }, { type: i1.Shops, decorators: [{
268
- type: Inject,
269
- args: [DEFAULT_SHOP]
270
- }] }, { type: undefined, decorators: [{
271
- type: Inject,
272
- args: ['ProductSearch']
273
- }] }]; } });
274
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2F0YWxvZy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY29ubmVjdC1hbmd1bGFyL3NyYy9zZXJ2aWNlcy9jYXRhbG9nL2NhdGFsb2cuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUNsRCxPQUFPLEVBSUwsb0JBQW9CLEVBVXBCLHdCQUF3QixFQUN4QixHQUFHLEVBQ0gsS0FBSyxFQUNMLEtBQUssR0FDTixNQUFNLG1CQUFtQixDQUFBO0FBQzFCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxZQUFZLEVBQUUsTUFBTSxjQUFjLENBQUE7OztBQXNEL0QsTUFBTSxPQUFPLGNBQWM7SUFHekIsWUFDZ0QsaUJBQW9DLEVBRWpFLGtDQUFzRSxFQUN4QyxrQkFBc0MsRUFDeEMsd0JBQWtELEVBQ3hELElBQVcsRUFDUixhQUFpQztRQU43QixzQkFBaUIsR0FBakIsaUJBQWlCLENBQW1CO1FBRWpFLHVDQUFrQyxHQUFsQyxrQ0FBa0MsQ0FBb0M7UUFDeEMsdUJBQWtCLEdBQWxCLGtCQUFrQixDQUFvQjtRQUN4Qyw2QkFBd0IsR0FBeEIsd0JBQXdCLENBQTBCO1FBQ3hELFNBQUksR0FBSixJQUFJLENBQU87UUFDUixrQkFBYSxHQUFiLGFBQWEsQ0FBb0I7UUFUckUsbUJBQWMsR0FBNkIsRUFBRSxDQUFBO1FBOFE3QyxxQkFBZ0IsR0FBRyxDQUFDLEVBQzFCLFlBQVksRUFDWixNQUFNLEVBQ04sTUFBTSxFQUNOLE1BQU0sRUFDTixJQUFJLEVBQ0osSUFBSSxFQUNKLGFBQWEsR0FDUSxFQUFtQyxFQUFFO1lBQzFELE1BQU0sT0FBTyxHQUFHLEVBQXFDLENBQUE7WUFFckQsSUFBSSxZQUFZLEVBQUUsTUFBTTtnQkFDdEIsR0FBRyxDQUFDLE9BQU8sRUFBRSxvQ0FBb0MsRUFBRSxFQUFFLFFBQVEsRUFB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QUMsUUFBUTtTQUMvQixDQUFBO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxJQUFZLEVBQUUsVUFBbUIsS0FBSztRQUN6RSxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDO1lBQUUsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFBO1FBRS9ELE9BQU8sQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxHQUFHLE1BQU0sSUFBSSxDQUFDLGFBQWE7YUFDekQsTUFBTSxDQUFnQixJQUFJLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxJQUFJLElBQUksS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7YUFDakYsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDN0UsQ0FBQzs7MkdBN1FVLGNBQWMsa0JBSWYsbUJBQW1CLGFBQ25CLG9DQUFvQyxhQUVwQyxvQkFBb0IsYUFDcEIsa0JBQWtCLGFBQ2xCLFlBQVksYUFDWixlQUFlOytHQVZkLGNBQWM7MkZBQWQsY0FBYztrQkFEMUIsVUFBVTs7MEJBS04sTUFBTTsyQkFBQyxtQkFBbUI7OzBCQUMxQixNQUFNOzJCQUFDLG9DQUFvQzs7MEJBRTNDLE1BQU07MkJBQUMsb0JBQW9COzswQkFDM0IsTUFBTTsyQkFBQyxrQkFBa0I7OzBCQUN6QixNQUFNOzJCQUFDLFlBQVk7OzBCQUNuQixNQUFNOzJCQUFDLGVBQWUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJ1xyXG5pbXBvcnQge1xyXG4gIENhdGVnb3J5LFxyXG4gIENhdGVnb3J5UmVwb3NpdG9yeSxcclxuICBGaW5kUmVwb3NpdG9yeVBhcmFtcyxcclxuICBJbnZhbGlkQXJndW1lbnRFcnJvcixcclxuICBQcm9kdWN0LFxyXG4gIFByb2R1Y3RHZW5kZXIsXHJcbiAgUHJvZHVjdFJlcG9zaXRvcnksXHJcbiAgUHJvZHVjdFNlYXJjaCxcclxuICBQcm9kdWN0U2VhcmNoSW5kZXgsXHJcbiAgUHJvZHVjdFN0b2NrTm90aWZpY2F0aW9uUmVwb3NpdG9yeSxcclxuICBSZXBvc2l0b3J5RmluZEZpZWx0ZXJzLFxyXG4gIFJlcG9zaXRvcnlGaW5kUmVzdWx0LFxyXG4gIFJlcG9zaXRvcnlPcmRlckJ5LFxyXG4gIFJvdW5kUHJvZHVjdFByaWNlc0hlbHBlcixcclxuICBzZXQsXHJcbiAgU2hvcHMsXHJcbiAgV2hlcmUsXHJcbn0gZnJvbSAnQGluZnJhYjRhL2Nvbm5lY3QnXHJcbmltcG9ydCB7IENBVEVHT1JZX1NUUlVDVFVSRSwgREVGQVVMVF9TSE9QIH0gZnJvbSAnLi4vLi4vY29uc3RzJ1xyXG5pbXBvcnQgeyBDYXRlZ29yeVN0cnVjdHVyZUFkYXB0ZXIgfSBmcm9tICcuL2FkYXB0ZXJzJ1xyXG5pbXBvcnQgeyBQcm9kdWN0U29ydCB9IGZyb20gJy4vdHlwZXMvcHJvZHVjdC1zb3J0LnR5cGUnXHJcblxyXG50eXBlIEZldGNoUHJvZHVjdHNGaWx0ZXJzID0ge1xyXG4gIGNsdWJEaXNjb3VudD86IG51bWJlcltdXHJcbiAgYnJhbmRzPzogc3RyaW5nW11cclxuICBwcmljZXM/OiB7IG1pbj86IG51bWJlcjsgbWF4PzogbnVtYmVyOyBzdWJzY3JpYmVyUHJpY2U/OiBib29sZWFuIH1cclxuICBnZW5kZXI/OiBQcm9kdWN0R2VuZGVyW11cclxuICByYXRlPzogbnVtYmVyXHJcbiAgY3VzdG9tT3B0aW9ucz86IHN0cmluZ1tdXHJcbiAgdGFncz86IHN0cmluZ1tdXHJcbn1cclxuXHJcbnR5cGUgRmV0Y2hQcm9kdWN0c09wdGlvbnMgPSB7XHJcbiAgcGFnZT86IG51bWJlclxyXG4gIHBlclBhZ2U/OiBudW1iZXJcclxuICBzb3J0PzogUHJvZHVjdFNvcnRcclxuICBtYWluR2VuZGVyPzogUHJvZHVjdEdlbmRlclxyXG59XHJcblxyXG50eXBlIEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQgZXh0ZW5kcyBDYXRlZ29yeT4gPSB7XHJcbiAgY2F0ZWdvcnk/OiBUXHJcbiAgcHJvZmlsZT86IHN0cmluZ1tdXHJcbiAgdGVybT86IHN0cmluZ1xyXG59XHJcblxyXG50eXBlIEZldGNoUHJvZHVjdHNQYXJhbXM8VCBleHRlbmRzIENhdGVnb3J5PiA9IEZldGNoUHJvZHVjdHNPcHRpb25zICZcclxuICAoXHJcbiAgICB8IHtcclxuICAgICAgICBjYXRlZ29yeTogRmV0Y2hQcm9kdWN0c01haW5QYXJhbXM8VD5bJ2NhdGVnb3J5J11cclxuICAgICAgICBmaWx0ZXJzPzogRmV0Y2hQcm9kdWN0c0ZpbHRlcnMgJiB7IGN1c3RvbU9wdGlvbnM/OiBuZXZlciB9XHJcbiAgICAgIH1cclxuICAgIHwge1xyXG4gICAgICAgIHByb2ZpbGU6IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+Wydwcm9maWxlJ11cclxuICAgICAgICBmaWx0ZXJzPzogRmV0Y2hQcm9kdWN0c0ZpbHRlcnMgJiB7IGN1c3RvbU9wdGlvbnM/OiBuZXZlcjsgdGFncz86IG5ldmVyIH1cclxuICAgICAgfVxyXG4gICAgfCB7XHJcbiAgICAgICAgdGVybTogRmV0Y2hQcm9kdWN0c01haW5QYXJhbXM8VD5bJ3Rlcm0nXVxyXG4gICAgICAgIGZpbHRlcnM/OiBGZXRjaFByb2R1Y3RzRmlsdGVycyAmIHsgY3VzdG9tT3B0aW9ucz86IG5ldmVyIH1cclxuICAgICAgfVxyXG4gIClcclxuXHJcbnR5cGUgRmV0Y2hQcm9kdWN0c1Jlc3BvbnNlID0ge1xyXG4gIHByb2R1Y3RzOiB7IGRhdGE6IFByb2R1Y3RbXTsgdG90YWw6IG51bWJlciB9XHJcbiAgcGFnZXM6IG51bWJlclxyXG4gIHByaWNlczoge1xyXG4gICAgcHJpY2U6IHsgbWluOiBudW1iZXI7IG1heDogbnVtYmVyIH1cclxuICAgIHN1YnNjcmliZXJQcmljZTogeyBtaW46IG51bWJlcjsgbWF4OiBudW1iZXIgfVxyXG4gIH1cclxuICBicmFuZHM/OiBzdHJpbmdbXVxyXG59XHJcblxyXG5ASW5qZWN0YWJsZSgpXHJcbmV4cG9ydCBjbGFzcyBDYXRhbG9nU2VydmljZTxUIGV4dGVuZHMgQ2F0ZWdvcnkgPSBDYXRlZ29yeT4ge1xyXG4gIHByaXZhdGUgcHJvZHVjdHNCeVRlcm06IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPiA9IHt9XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgQEluamVjdCgnUHJvZHVjdFJlcG9zaXRvcnknKSBwcml2YXRlIHJlYWRvbmx5IHByb2R1Y3RSZXBvc2l0b3J5OiBQcm9kdWN0UmVwb3NpdG9yeSxcclxuICAgIEBJbmplY3QoJ1Byb2R1Y3RTdG9ja05vdGlmaWNhdGlvblJlcG9zaXRvcnknKVxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBwcm9kdWN0U3RvY2tOb3RpZmljYXRpb25SZXBvc2l0b3J5OiBQcm9kdWN0U3RvY2tOb3RpZmljYXRpb25SZXBvc2l0b3J5LFxyXG4gICAgQEluamVjdCgnQ2F0ZWdvcnlSZXBvc2l0b3J5JykgcHJpdmF0ZSByZWFkb25seSBjYXRlZ29yeVJlcG9zaXRvcnk6IENhdGVnb3J5UmVwb3NpdG9yeSxcclxuICAgIEBJbmplY3QoQ0FURUdPUllfU1RSVUNUVVJFKSBwcml2YXRlIHJlYWRvbmx5IGNhdGVnb3J5U3RydWN0dXJlQWRhcHRlcjogQ2F0ZWdvcnlTdHJ1Y3R1cmVBZGFwdGVyLFxyXG4gICAgQEluamVjdChERUZBVUxUX1NIT1ApIHByaXZhdGUgcmVhZG9ubHkgc2hvcDogU2hvcHMsXHJcbiAgICBASW5qZWN0KCdQcm9kdWN0U2VhcmNoJykgcHJpdmF0ZSByZWFkb25seSBwcm9kdWN0U2VhcmNoOiBQcm9kdWN0U2VhcmNoSW5kZXgsXHJcbiAgKSB7fVxyXG5cclxuICBhc3luYyBmZXRjaFByb2R1Y3RzKG9wdGlvbnM6IEZldGNoUHJvZHVjdHNQYXJhbXM8VD4pOiBQcm9taXNlPEZldGNoUHJvZHVjdHNSZXNwb25zZT4ge1xyXG4gICAgY29uc3QgbGltaXRzID0gdGhpcy5idWlsZExpbWl0UXVlcnkob3B0aW9ucylcclxuXHJcbiAgICBpZiAodGhpcy5oYXNQcm9maWxlKG9wdGlvbnMpICYmIG9wdGlvbnMuZmlsdGVycz8uY3VzdG9tT3B0aW9ucylcclxuICAgICAgdGhyb3cgbmV3IEludmFsaWRBcmd1bWVudEVycm9yKGBJdCBjb3VsZG4ndCBmaWxsZWQgY3VzdG9tT3B0aW9ucyB3aGVuIHByb2ZpbGUgaXMgZ2l2ZW5gKVxyXG4gICAgaWYgKHRoaXMuaGFzUHJvZmlsZShvcHRpb25zKSAmJiBvcHRpb25zLmZpbHRlcnM/LnRhZ3MpXHJcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQXJndW1lbnRFcnJvcihgSXQgY291bGRuJ3QgZmlsbGVkIHRhZ3Mgd2hlbiBwcm9maWxlIGlzIGdpdmVuYClcclxuICAgIGlmICh0aGlzLmhhc1Rlcm0ob3B0aW9ucykgJiYgb3B0aW9ucy5maWx0ZXJzPy5jdXN0b21PcHRpb25zKVxyXG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFyZ3VtZW50RXJyb3IoYEl0IGNvdWxkbid0IGZpbGxlZCBjdXN0b21PcHRpb25zIHdoZW4gdGVybSBpcyBnaXZlbmApXHJcblxyXG4gICAgY29uc29sZS5sb2coJ2ZldGNoUHJvZHVjdHMnLCBvcHRpb25zKVxyXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuZmluZENhdGFsb2cob3B0aW9ucywgbGltaXRzKS50aGVuKCh7IGRhdGEsIGNvdW50OiB0b3RhbCwgbWF4aW11bSwgbWluaW1hbCwgZGlzdGluY3QgfSkgPT4gKHtcclxuICAgICAgcHJvZHVjdHM6IHsgZGF0YTogZGF0YS5tYXAoKHByb2R1Y3QpID0+IFJvdW5kUHJvZHVjdFByaWNlc0hlbHBlci5yb3VuZFByb2R1Y3RQcmljZXMocHJvZHVjdCkpLCB0b3RhbCB9LFxyXG4gICAgICBwYWdlczogTWF0aC5jZWlsKHRvdGFsIC8gbGltaXRzLmxpbWl0KSxcclxuICAgICAgcHJpY2VzOiB7XHJcbiAgICAgICAgcHJpY2U6IHsgbWluOiArbWluaW1hbD8ucHJpY2U/LnByaWNlPy50b0ZpeGVkKDIpLCBtYXg6ICttYXhpbXVtPy5wcmljZT8ucHJpY2U/LnRvRml4ZWQoMikgfSxcclxuICAgICAgICBzdWJzY3JpYmVyUHJpY2U6IHtcclxuICAgICAgICAgIG1pbjogK21pbmltYWw/LnByaWNlPy5zdWJzY3JpYmVyUHJpY2U/LnRvRml4ZWQoMiksXHJcbiAgICAgICAgICBtYXg6ICttYXhpbXVtPy5wcmljZT8uc3Vic2NyaWJlclByaWNlPy50b0ZpeGVkKDIpLFxyXG4gICAgICAgIH0sXHJcbiAgICAgIH0sXHJcbiAgICAgIGJyYW5kczogZGlzdGluY3Q/LmJyYW5kLFxyXG4gICAgfSkpXHJcbiAgfVxyXG5cclxuICBhc3luYyBhZGRDdXN0b21lclRvU3RvY2tOb3RpZmljYXRpb24oc2hvcDogU2hvcHMsIHByb2R1Y3RJZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcsIGVtYWlsOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIHJldHVybiB0aGlzLnByb2R1Y3RTdG9ja05vdGlmaWNhdGlvblJlcG9zaXRvcnkuYWRkQ3VzdG9tZXJFbWFpbChzaG9wLCBwcm9kdWN0SWQsIG5hbWUsIGVtYWlsKVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBmaW5kQ2F0YWxvZyhcclxuICAgIG9wdGlvbnM6IEZldGNoUHJvZHVjdHNQYXJhbXM8VD4sXHJcbiAgICBsaW1pdHM6IHtcclxuICAgICAgbGltaXQ/OiBudW1iZXJcclxuICAgICAgb2Zmc2V0PzogbnVtYmVyXHJcbiAgICB9LFxyXG4gICk6IFByb21pc2U8UmVwb3NpdG9yeUZpbmRSZXN1bHQ8UHJvZHVjdD4+IHtcclxuICAgIGlmICh0aGlzLmhhc1Rlcm0ob3B0aW9ucykgJiYgb3B0aW9ucy5zb3J0ID09PSAnbW9zdC1yZWxldmFudCcpIHtcclxuICAgICAgLy8gY29uc29sZS5sb2coJ1N0ZXAgMScpXHJcbiAgICAgIGNvbnN0IHByb2R1Y3RzSWRzID0gYXdhaXQgdGhpcy5maW5kQ2F0YWxvZ0lkc0J5U2VhcmNoKG9wdGlvbnMudGVybSlcclxuXHJcbiAgICAgIHJldHVybiB0aGlzLmZpbmRDYXRhbG9nQW5kU29ydEJ5TW9zdFJldmVsYW50QnlUZXJtKHByb2R1Y3RzSWRzLCBvcHRpb25zLCBsaW1pdHMpXHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuaGFzQ2F0ZWdvcnkob3B0aW9ucykgJiYgb3B0aW9ucy5zb3J0ID09PSAnbW9zdC1yZWxldmFudCcpIHtcclxuICAgICAgY29uc3QgbW9zdFJlbGV2YW50ID0gb3B0aW9ucy5jYXRlZ29yeS5pc1dpc2hsaXN0ID8gW10gOiBvcHRpb25zLmNhdGVnb3J5LmdldE1vc3RSZWxldmFudEJ5U2hvcCh0aGlzLnNob3ApXHJcbiAgICAgIGNvbnN0IHByb2R1Y3RzSWRzID0gYXdhaXQgdGhpcy5wcm9kdWN0UmVwb3NpdG9yeVxyXG4gICAgICAgIC5maW5kQ2F0YWxvZyh7XHJcbiAgICAgICAgICBmaWVsZHM6IFsnaWQnXSxcclxuICAgICAgICAgIGZpbHRlcnM6IHtcclxuICAgICAgICAgICAgLi4uKGF3YWl0IHRoaXMuYnVpbGRNYWluRmlsdGVyKG9wdGlvbnMpKSxcclxuICAgICAgICAgICAgLi4udGhpcy5idWlsZEZpbHRlclF1ZXJ5KG9wdGlvbnM/LmZpbHRlcnMgfHwge30pLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9KVxyXG4gICAgICAgIC50aGVuKChwcm9kdWN0cykgPT4gcHJvZHVjdHMuZGF0YS5tYXAoKHByb2R1Y3QpID0+IHByb2R1Y3QuaWQpKVxyXG5cclxuICAgICAgcmV0dXJuIHRoaXMuZmluZENhdGFsb2dBbmRTb3J0QnlNb3N0UmV2ZWxhbnQobW9zdFJlbGV2YW50LCBwcm9kdWN0c0lkcywgb3B0aW9ucywgbGltaXRzKVxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHJlcG9QYXJhbXM6IEZpbmRSZXBvc2l0b3J5UGFyYW1zPFByb2R1Y3Q+ID0ge1xyXG4gICAgICBmaWx0ZXJzOiB7XHJcbiAgICAgICAgLi4uKGF3YWl0IHRoaXMuYnVpbGRNYWluRmlsdGVyKG9wdGlvbnMpKSxcclxuICAgICAgICAuLi50aGlzLmJ1aWxkRmlsdGVyUXVlcnkob3B0aW9ucz8uZmlsdGVycyB8fCB7fSksXHJcbiAgICAgIH0sXHJcbiAgICAgIC4uLihvcHRpb25zPy5zb3J0ID8geyBvcmRlckJ5OiB0aGlzLmJ1aWxkU29ydFF1ZXJ5KG9wdGlvbnM/LnNvcnQpIH0gOiB7fSksXHJcbiAgICAgIGxpbWl0cyxcclxuICAgICAgb3B0aW9uczoge1xyXG4gICAgICAgIG1pbmltYWw6IFsncHJpY2UnXSxcclxuICAgICAgICBtYXhpbXVtOiBbJ3ByaWNlJ10sXHJcbiAgICAgICAgLi4uKCF0aGlzLmhhc0NhdGVnb3J5KG9wdGlvbnMpID8geyBkaXN0aW5jdDogWydicmFuZCddIH0gOiB7fSksXHJcbiAgICAgIH0sXHJcbiAgICB9XHJcblxyXG4gICAgaWYgKFsnYmlnZ2VzdC1wcmljZScsICdsb3dlc3QtcHJpY2UnLCAnYmlnZ2VzdC1kaXNjb3VudCcsICdiZXN0LXJhdGluZyddLmluY2x1ZGVzKG9wdGlvbnMuc29ydCkpXHJcbiAgICAgIHJldHVybiB0aGlzLnByb2R1Y3RSZXBvc2l0b3J5LmZpbmRDYXRhbG9nKHJlcG9QYXJhbXMpXHJcblxyXG4gICAgcmV0dXJuIHRoaXMucHJvZHVjdFJlcG9zaXRvcnkuZmluZENhdGFsb2coXHJcbiAgICAgIHJlcG9QYXJhbXMsXHJcbiAgICAgIG9wdGlvbnM/Lm1haW5HZW5kZXIgfHwgdGhpcy5zaG9wID09PSBTaG9wcy5NRU5TTUFSS0VUID8gJ21hbGUnIDogJ2ZlbWFsZScsXHJcbiAgICApXHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGFzeW5jIGJ1aWxkTWFpbkZpbHRlcih7XHJcbiAgICBjYXRlZ29yeSxcclxuICAgIHByb2ZpbGUsXHJcbiAgICB0ZXJtLFxyXG4gIH06IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+KTogUHJvbWlzZTxSZXBvc2l0b3J5RmluZEZpZWx0ZXJzPFByb2R1Y3Q+PiB7XHJcbiAgICBpZiAoY2F0ZWdvcnkpIHJldHVybiB0aGlzLmNhdGVnb3J5U3RydWN0dXJlQWRhcHRlci5idWlsZFByb2R1Y3RGaWx0ZXJCeUNhdGVnb3J5KGNhdGVnb3J5KVxyXG4gICAgaWYgKHByb2ZpbGUpIHJldHVybiB7IHRhZ3M6IHsgb3BlcmF0b3I6IFdoZXJlLkxJS0UsIHZhbHVlOiBwcm9maWxlIH0gfVxyXG4gICAgaWYgKHRlcm0pXHJcbiAgICAgIHJldHVybiB0aGlzLnByb2R1Y3RTZWFyY2hcclxuICAgICAgICAuc2VhcmNoPFByb2R1Y3Q+KHRlcm0sIDk5OSwgdGhpcy5zaG9wID09IFNob3BzLkdMQU1TSE9QID8gJ2ZlbWFsZScgOiAnbWFsZScpXHJcbiAgICAgICAgLnRoZW4oKGRhdGEpID0+ICh7IGlkOiB7IG9wZXJhdG9yOiBXaGVyZS5JTiwgdmFsdWU6IGRhdGEubWFwKChfc291cmNlKSA9PiBfc291cmNlLmlkKSB9IH0pKVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBmaW5kQ2F0YWxvZ0FuZFNvcnRCeU1vc3RSZXZlbGFudChcclxuICAgIG1vc3RSZWxldmFudHM6IHN0cmluZ1tdLFxyXG4gICAgcHJvZHVjdElkczogc3RyaW5nW10sXHJcbiAgICBvcHRpb25zOiBPbWl0PEZldGNoUHJvZHVjdHNPcHRpb25zLCAnc29ydCc+ICYge1xyXG4gICAgICB0ZXJtPzogRmV0Y2hQcm9kdWN0c01haW5QYXJhbXM8VD5bJ3Rlcm0nXVxyXG4gICAgICBmaWx0ZXJzPzogRmV0Y2hQcm9kdWN0c0ZpbHRlcnMgJiB7IGN1c3RvbU9wdGlvbnM/OiBuZXZlciB9XHJcbiAgICB9LFxyXG4gICAgbGltaXRzOiB7XHJcbiAgICAgIGxpbWl0PzogbnVtYmVyXHJcbiAgICAgIG9mZnNldD86IG51bWJlclxyXG4gICAgfSxcclxuICApOiBQcm9taXNlPFJlcG9zaXRvcnlGaW5kUmVzdWx0PFByb2R1Y3Q+PiB7XHJcbiAgICBjb25zdCBtb3N0UmVsZXZhbnRQcm9kdWN0c0lkcyA9IFsuLi5uZXcgU2V0KG1vc3RSZWxldmFudHMuY29uY2F0KHByb2R1Y3RJZHMpKV1cclxuICAgIGNvbnN0IHRvdGFsUmVzdWx0ID0gYXdhaXQgdGhpcy5wcm9kdWN0UmVwb3NpdG9yeS5maW5kQ2F0YWxvZyhcclxuICAgICAge1xyXG4gICAgICAgIGZpbHRlcnM6IHtcclxuICAgICAgICAgIGlkOiB7IG9wZXJhdG9yOiBXaGVyZS5JTiwgdmFsdWU6IG1vc3RSZWxldmFudFByb2R1Y3RzSWRzIH0sXHJcbiAgICAgICAgICAuLi50aGlzLmJ1aWxkRmlsdGVyUXVlcnkob3B0aW9ucz8uZmlsdGVycyB8fCB7fSksXHJcbiAgICAgICAgfSxcclxuICAgICAgICBvcmRlckJ5OiB0aGlzLmJ1aWxkU29ydFF1ZXJ5KCdiZXN0LXNlbGxlcnMnKSxcclxuICAgICAgICBvcHRpb25zOiB7XHJcbiAgICAgICAgICBtaW5pbWFsOiBbJ3ByaWNlJ10sXHJcbiAgICAgICAgICBtYXhpbXVtOiBbJ3ByaWNlJ10sXHJcbiAgICAgICAgICBkaXN0aW5jdDogWydicmFuZCddLFxyXG4gICAgICAgIH0sXHJcbiAgICAgIH0sXHJcbiAgICAgIG9wdGlvbnM/Lm1haW5HZW5kZXIgfHwgdGhpcy5zaG9wID09PSBTaG9wcy5NRU5TTUFSS0VUID8gJ21hbGUnIDogJ2ZlbWFsZScsXHJcbiAgICApXHJcblxyXG4gICAgY29uc3QgbW9zdFJlbGV2YW50V2l0aG91eVN0b2NrID0gdG90YWxSZXN1bHQuZGF0YS5maWx0ZXIoXHJcbiAgICAgIChwcm9kdWN0KSA9PiBtb3N0UmVsZXZhbnRzLmluY2x1ZGVzKHByb2R1Y3QuaWQpICYmIHByb2R1Y3Quc3RvY2sucXVhbnRpdHkgPD0gMCxcclxuICAgIClcclxuICAgIGNvbnN0IGZpcnN0UHJvZHVjdHMgPSB0b3RhbFJlc3VsdC5kYXRhXHJcbiAgICAgIC5maWx0ZXIoKHByb2R1Y3QpID0+IG1vc3RSZWxldmFudHMuaW5jbHVkZXMocHJvZHVjdC5pZCkgJiYgcHJvZHVjdC5zdG9jay5xdWFudGl0eSA+IDApXHJcbiAgICAgIC5zb3J0KChhLCBiKSA9PiBtb3N0UmVsZXZhbnRzLmluZGV4T2YoYS5pZCkgLSBtb3N0UmVsZXZhbnRzLmluZGV4T2YoYi5pZCkpXHJcbiAgICBjb25zdCBsYXN0UHJvZHVjdHMgPSB0b3RhbFJlc3VsdC5kYXRhXHJcbiAgICAgIC5maWx0ZXIoKHByb2R1Y3QpID0+ICFtb3N0UmVsZXZhbnRzLmluY2x1ZGVzKHByb2R1Y3QuaWQpKVxyXG4gICAgICAuY29uY2F0KG1vc3RSZWxldmFudFdpdGhvdXlTdG9jaylcclxuICAgIGNvbnN0IGNhdGVnb3J5TW9zdFJlbGV2YW50cyA9IGZpcnN0UHJvZHVjdHMuY29uY2F0KGxhc3RQcm9kdWN0cylcclxuICAgIGNvbnN0IHJlc3VsdEZpbmFsID0gY2F0ZWdvcnlNb3N0UmVsZXZhbnRzLnNsaWNlKGxpbWl0cy5vZmZzZXQsIGxpbWl0cy5vZmZzZXQgKyBsaW1pdHMubGltaXQpXHJcblxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgZGF0YTogcmVzdWx0RmluYWwsXHJcbiAgICAgIGNvdW50OiB0b3RhbFJlc3VsdC5jb3VudCxcclxuICAgICAgbWF4aW11bTogdG90YWxSZXN1bHQubWF4aW11bSxcclxuICAgICAgbWluaW1hbDogdG90YWxSZXN1bHQubWluaW1hbCxcclxuICAgICAgZGlzdGluY3Q6IHRvdGFsUmVzdWx0LmRpc3RpbmN0LFxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBmaW5kQ2F0YWxvZ0FuZFNvcnRCeU1vc3RSZXZlbGFudEJ5VGVybShcclxuICAgIHByb2R1Y3RJZHM6IHN0cmluZ1tdLFxyXG4gICAgb3B0aW9uczogT21pdDxGZXRjaFByb2R1Y3RzT3B0aW9ucywgJ3NvcnQnPiAmIHtcclxuICAgICAgdGVybT86IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+Wyd0ZXJtJ11cclxuICAgICAgZmlsdGVycz86IEZldGNoUHJvZHVjdHNGaWx0ZXJzICYgeyBjdXN0b21PcHRpb25zPzogbmV2ZXIgfVxyXG4gICAgfSxcclxuICAgIGxpbWl0czoge1xyXG4gICAgICBsaW1pdD86IG51bWJlclxyXG4gICAgICBvZmZzZXQ/OiBudW1iZXJcclxuICAgIH0sXHJcbiAgKTogUHJvbWlzZTxSZXBvc2l0b3J5RmluZFJlc3VsdDxQcm9kdWN0Pj4ge1xyXG4gICAgLy8gY29uc29sZS5sb2coJ2ZpbmRDYXRhbG9nQW5kU29ydEJ5TW9zdFJldmVsYW50QnlUZXJtJywgdGhpcy5zaG9wLCBvcHRpb25zLCBsaW1pdHMpXHJcbiAgICAvLyBjb25zb2xlLmxvZyhcclxuICAgIC8vICAgJ3Byb2R1Y3RJZHMgZnJvbSBzZWFyY2gnLFxyXG4gICAgLy8gICBwcm9kdWN0SWRzLmxlbmd0aCxcclxuICAgIC8vICAgJ3ByZXZpZXcgLT4gJyxcclxuICAgIC8vICAgcHJvZHVjdElkcy5zbGljZShsaW1pdHMub2Zmc2V0LCBsaW1pdHMub2Zmc2V0ICsgbGltaXRzLmxpbWl0KSxcclxuICAgIC8vIClcclxuICAgIGNvbnN0IHRvdGFsUmVzdWx0ID0gYXdhaXQgdGhpcy5wcm9kdWN0UmVwb3NpdG9yeS5maW5kQ2F0YWxvZyhcclxuICAgICAge1xyXG4gICAgICAgIGZpZWxkczogWydpZCcsICdzdG9jaycsICdnZW5kZXInXSxcclxuICAgICAgICBmaWx0ZXJzOiB7XHJcbiAgICAgICAgICBpZDogeyBvcGVyYXRvcjogV2hlcmUuSU4sIHZhbHVlOiBwcm9kdWN0SWRzIH0sXHJcbiAgICAgICAgICBwdWJsaXNoZWQ6IHsgb3BlcmF0b3I6IFdoZXJlLkVRVUFMUywgdmFsdWU6IHRydWUgfSxcclxuICAgICAgICAgIC4uLnRoaXMuYnVpbGRGaWx0ZXJRdWVyeShvcHRpb25zPy5maWx0ZXJzIHx8IHt9KSxcclxuICAgICAgICB9LFxyXG4gICAgICAgIG9wdGlvbnM6IHtcclxuICAgICAgICAgIG1pbmltYWw6IFsncHJpY2UnXSxcclxuICAgICAgICAgIG1heGltdW06IFsncHJpY2UnXSxcclxuICAgICAgICAgIGRpc3RpbmN0OiBbJ2JyYW5kJ10sXHJcbiAgICAgICAgfSxcclxuICAgICAgfSxcclxuICAgICAgb3B0aW9ucz8ubWFpbkdlbmRlciB8fCB0aGlzLnNob3AgPT09IFNob3BzLk1FTlNNQVJLRVQgPyAnbWFsZScgOiAnZmVtYWxlJyxcclxuICAgIClcclxuXHJcbiAgICAvLyBjb25zdCBwcm9kdWN0c1RvdGFsUmVzdWx0ID0gdG90YWxSZXN1bHQuZGF0YS5zbGljZShsaW1pdHMub2Zmc2V0LCBsaW1pdHMub2Zmc2V0ICsgbGltaXRzLmxpbWl0KVxyXG4gICAgLy8gY29uc29sZS5sb2coXHJcbiAgICAvLyAgICdwcm9kdWN0c1RvdGFsUmVzdWx0JyxcclxuICAgIC8vICAgcHJvZHVjdHNUb3RhbFJlc3VsdC5tYXAoKHApID0+IHtcclxuICAgIC8vICAgICByZXR1cm4ge1xyXG4gICAgLy8gICAgICAgaWQ6IHAuaWQsXHJcbiAgICAvLyAgICAgICBzdG9jazogcC5zdG9jay5xdWFudGl0eSxcclxuICAgIC8vICAgICB9XHJcbiAgICAvLyAgIH0pLFxyXG4gICAgLy8gKVxyXG5cclxuICAgIGNvbnN0IGRlZmF1bHRHZW5kZXIgPSBvcHRpb25zPy5maWx0ZXJzPy5nZW5kZXJcclxuICAgICAgPyBvcHRpb25zPy5maWx0ZXJzPy5nZW5kZXIuYXQoMClcclxuICAgICAgOiB0aGlzLnNob3AgPT09IFNob3BzLkdMQU1TSE9QXHJcbiAgICAgID8gJ2ZlbWFsZSdcclxuICAgICAgOiAnbWFsZSdcclxuXHJcbiAgICBjb25zdCBzdG9ja0RhdGEgPSB0b3RhbFJlc3VsdC5kYXRhLmZpbHRlcigocHJvZHVjdCkgPT4gcHJvZHVjdC5zdG9jay5xdWFudGl0eSA+IDApXHJcbiAgICBjb25zdCBzdG9ja091dCA9IHRvdGFsUmVzdWx0LmRhdGEuZmlsdGVyKChwcm9kdWN0KSA9PiBwcm9kdWN0LnN0b2NrLnF1YW50aXR5IDw9IDApXHJcbiAgICBjb25zdCBwcm9kdWN0SWRzU3RvY2tHZW5kZXIgPSBwcm9kdWN0SWRzLmZpbHRlcigocHJvZHVjdCkgPT5cclxuICAgICAgc3RvY2tEYXRhLnNvbWUoXHJcbiAgICAgICAgKHJlc3VsdCkgPT5cclxuICAgICAgICAgIHJlc3VsdC5pZCA9PT0gcHJvZHVjdCAmJiAocmVzdWx0LmdlbmRlcj8uaW5jbHVkZXMoZGVmYXVsdEdlbmRlcikgfHwgcmVzdWx0LmdlbmRlcj8uaW5jbHVkZXMoJ3VuaXNleCcpKSxcclxuICAgICAgKSxcclxuICAgIClcclxuICAgIGNvbnN0IHByb2R1Y3RJZHNTdG9ja05vdEdlbmRlciA9IHByb2R1Y3RJZHMuZmlsdGVyKChwcm9kdWN0KSA9PlxyXG4gICAgICBzdG9ja0RhdGEuc29tZShcclxuICAgICAgICAocmVzdWx0KSA9PlxyXG4gICAgICAgICAgcmVzdWx0LmlkID09PSBwcm9kdWN0ICYmICFyZXN1bHQuZ2VuZGVyPy5pbmNsdWRlcyhkZWZhdWx0R2VuZGVyKSAmJiAhcmVzdWx0LmdlbmRlcj8uaW5jbHVkZXMoJ3VuaXNleCcpLFxyXG4gICAgICApLFxyXG4gICAgKVxyXG4gICAgY29uc3QgcHJvZHVjdElkc1N0b2NrID0gcHJvZHVjdElkc1N0b2NrR2VuZGVyLmNvbmNhdChwcm9kdWN0SWRzU3RvY2tOb3RHZW5kZXIpXHJcbiAgICBjb25zdCBwcm9kdWN0SWRzU3RvY2tPdXQgPSBwcm9kdWN0SWRzLmZpbHRlcigocHJvZHVjdCkgPT4gc3RvY2tPdXQuc29tZSgocmVzdWx0KSA9PiByZXN1bHQuaWQgPT09IHByb2R1Y3QpKVxyXG5cclxuICAgIGNvbnN0IGxpbWl0ZWRQcm9kdWN0SWQgPSBwcm9kdWN0SWRzU3RvY2tcclxuICAgICAgLmNvbmNhdChwcm9kdWN0SWRzU3RvY2tPdXQpXHJcbiAgICAgIC5zbGljZShsaW1pdHMub2Zmc2V0LCBsaW1pdHMub2Zmc2V0ICsgbGltaXRzLmxpbWl0KVxyXG5cclxuICAgIC8vIGNvbnNvbGUubG9nKCdsaW1pdGVkUHJvZHVjdElkJywgbGltaXRlZFByb2R1Y3RJZClcclxuICAgIGNvbnN0IG9yZGVyZWRJZCA9IHByb2R1Y3RJZHMuZmlsdGVyKChwcm9kdWN0KSA9PiBsaW1pdGVkUHJvZHVjdElkLmluY2x1ZGVzKHByb2R1Y3QpKVxyXG5cclxuICAgIGNvbnN0IHByb2R1Y3RSZXN1bHQgPSBhd2FpdCB0aGlzLnByb2R1Y3RSZXBvc2l0b3J5LmZpbmRDYXRhbG9nKHtcclxuICAgICAgZmlsdGVyczoge1xyXG4gICAgICAgIGlkOiB7IG9wZXJhdG9yOiBXaGVyZS5JTiwgdmFsdWU6IG9yZGVyZWRJZCB9LFxyXG4gICAgICB9LFxyXG4gICAgfSlcclxuXHJcbiAgICBjb25zdCBmaW5hbFJlc3VsdCA9IGxpbWl0ZWRQcm9kdWN0SWRcclxuICAgICAgLm1hcCgoaWQpID0+IHByb2R1Y3RSZXN1bHQuZGF0YS5maW5kKChwcm9kdWN0KSA9PiBwcm9kdWN0LmlkID09PSBpZCkpXHJcbiAgICAgIC5maWx0ZXIoQm9vbGVhbilcclxuXHJcbiAgICAvLyBjb25zb2xlLmxvZyhcclxuICAgIC8vICAgJ2ZpbmFsUmVzdWx0JyxcclxuICAgIC8vICAgZmluYWxSZXN1bHQubWFwKChwKSA9PiB7XHJcbiAgICAvLyAgICAgcmV0dXJuIHtcclxuICAgIC8vICAgICAgIGlkOiBwLmlkLFxyXG4gICAgLy8gICAgICAgbmFtZTogcC5uYW1lLFxyXG4gICAgLy8gICAgICAgYnJhbmQ6IHAuYnJhbmQsXHJcbiAgICAvLyAgICAgfVxyXG4gICAgLy8gICB9KSxcclxuICAgIC8vIClcclxuXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBkYXRhOiBsaW1pdGVkUHJvZHVjdElkLm1hcCgoaWQpID0+IHByb2R1Y3RSZXN1bHQuZGF0YS5maW5kKChwcm9kdWN0KSA9PiBwcm9kdWN0LmlkID09PSBpZCkpLmZpbHRlcihCb29sZWFuKSxcclxuICAgICAgY291bnQ6IHRvdGFsUmVzdWx0LmNvdW50LFxyXG4gICAgICBtYXhpbXVtOiB0b3RhbFJlc3VsdC5tYXhpbXVtLFxyXG4gICAgICBtaW5pbWFsOiB0b3RhbFJlc3VsdC5taW5pbWFsLFxyXG4gICAgICBkaXN0aW5jdDogdG90YWxSZXN1bHQuZGlzdGluY3QsXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGFzeW5jIGZpbmRDYXRhbG9nSWRzQnlTZWFyY2godGVybTogc3RyaW5nLCBwcmV2aWV3OiBib29sZWFuID0gZmFsc2UpOiBQcm9taXNlPHN0cmluZ1tdPiB7XHJcbiAgICBpZiAodGhpcy5wcm9kdWN0c0J5VGVybVt0ZXJtXSkgcmV0dXJuIHRoaXMucHJvZHVjdHNCeVRlcm1bdGVybV1cclxuXHJcbiAgICByZXR1cm4gKHRoaXMucHJvZHVjdHNCeVRlcm1bdGVybV0gPSBhd2FpdCB0aGlzLnByb2R1Y3RTZWFyY2hcclxuICAgICAgLnNlYXJjaDxQcm9kdWN0U2VhcmNoPih0ZXJtLCA5OTksIHRoaXMuc2hvcCA9PSBTaG9wcy5HTEFNU0hPUCA/ICdmZW1hbGUnIDogJ21hbGUnKVxyXG4gICAgICAudGhlbigocHJvZHVjdHMpID0+IFsuLi5uZXcgU2V0KHByb2R1Y3RzLm1hcCgocHJvZHVjdCkgPT4gcHJvZHVjdC5pZCkpXSkpXHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGJ1aWxkRmlsdGVyUXVlcnkgPSAoe1xyXG4gICAgY2x1YkRpc2NvdW50LFxyXG4gICAgYnJhbmRzLFxyXG4gICAgcHJpY2VzLFxyXG4gICAgZ2VuZGVyLFxyXG4gICAgdGFncyxcclxuICAgIHJhdGUsXHJcbiAgICBjdXN0b21PcHRpb25zLFxyXG4gIH06IEZldGNoUHJvZHVjdHNGaWx0ZXJzKTogUmVwb3NpdG9yeUZpbmRGaWVsdGVyczxQcm9kdWN0PiA9PiB7XHJcbiAgICBjb25zdCBmaWx0ZXJzID0ge30gYXMgUmVwb3NpdG9yeUZpbmRGaWVsdGVyczxQcm9kdWN0PlxyXG5cclxuICAgIGlmIChjbHViRGlzY291bnQ/Lmxlbmd0aClcclxuICAgICAgc2V0KGZpbHRlcnMsICdwcmljZS5zdWJzY3JpYmVyRGlzY291bnRQZXJjZW50YWdlJywgeyBvcGVyYXRvcjogV2hlcmUuSU4sIHZhbHVlOiBjbHViRGlzY291bnQgfSlcclxuICAgIGlmIChicmFuZHM/Lmxlbmd0aCkgZmlsdGVycy5icmFuZCA9IHsgb3BlcmF0b3I6IFdoZXJlLklOLCB2YWx1ZTogYnJhbmRzIH1cclxuICAgIGlmIChnZW5kZXI/Lmxlbmd0aCkgZmlsdGVycy5nZW5kZXIgPSB7IG9wZXJhdG9yOiBXaGVyZS5JTiwgdmFsdWU6IGdlbmRlciB9XHJcbiAgICBpZiAocHJpY2VzPy5taW4gfHwgcHJpY2VzPy5tYXgpXHJcbiAgICAgIHNldChmaWx0ZXJzLCBwcmljZXMuc3Vic2NyaWJlclByaWNlID8gJ3ByaWNlLnN1YnNjcmliZXJQcmljZScgOiAncHJpY2UucHJpY2UnLCBbXHJcbiAgICAgICAgLi4uKHByaWNlcy5taW4gPyBbeyBvcGVyYXRvcjogV2hlcmUuR1RFLCB2YWx1ZTogTWF0aC5yb3VuZChwcmljZXMubWluKSB9XSA6IFtdKSxcclxuICAgICAgICAuLi4ocHJpY2VzLm1heCA/IFt7IG9wZXJhdG9yOiBXaGVyZS5MVEUsIHZhbHVlOiBNYXRoLmNlaWwocHJpY2VzLm1heCkgfV0gOiBbXSksXHJcbiAgICAgIF0pXHJcbiAgICBpZiAocmF0ZSkgZmlsdGVycy5yYXRlID0geyBvcGVyYXRvcjogV2hlcmUuR1RFLCB2YWx1ZTogcmF0ZSB9XHJcbiAgICBpZiAodGFncz8ubGVuZ3RoKSBmaWx0ZXJzLnRhZ3MgPSB7IG9wZXJhdG9yOiBXaGVyZS5MSUtFLCB2YWx1ZTogdGFncyB9XHJcbiAgICBpZiAoY3VzdG9tT3B0aW9ucz8ubGVuZ3RoKSBmaWx0ZXJzLmZpbHRlcnMgPSB7IG9wZXJhdG9yOiBXaGVyZS5MSUtFLCB2YWx1ZTogY3VzdG9tT3B0aW9ucyB9XHJcblxyXG4gICAgcmV0dXJuIGZpbHRlcnNcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYnVpbGRTb3J0UXVlcnkgPSAoc29ydDogUHJvZHVjdFNvcnQpOiBSZXBvc2l0b3J5T3JkZXJCeTxQcm9kdWN0PiA9PiB7XHJcbiAgICBpZiAoIXNvcnQgfHwgc29ydCA9PT0gJ21vc3QtcmVsZXZhbnQnKSByZXR1cm4ge31cclxuXHJcbiAgICBpZiAoc29ydCA9PT0gJ2Jlc3Qtc2VsbGVycycpXHJcbiAgICAgIHJldHVybiB7XHJcbiAgICAgICAgc2hvcHBpbmdDb3VudDogJ2Rlc2MnLFxyXG4gICAgICAgIHJhdGU6ICdkZXNjJyxcclxuICAgICAgICBzdG9jazogJ2Rlc2MnLFxyXG4gICAgICAgIG5hbWU6ICdhc2MnLFxyXG4gICAgICB9XHJcbiAgICBpZiAoc29ydCA9PT0gJ2JpZ2dlc3QtcHJpY2UnKSByZXR1cm4geyBzdWJzY3JpYmVyUHJpY2U6ICdkZXNjJywgcmF0ZTogJ2Rlc2MnLCBzaG9wcGluZ0NvdW50OiAnZGVzYycgfSBhcyBhbnlcclxuICAgIGlmIChzb3J0ID09PSAnbG93ZXN0LXByaWNlJykgcmV0dXJuIHsgc3Vic2NyaWJlclByaWNlOiAnYXNjJywgcmF0ZTogJ2Rlc2MnLCBzaG9wcGluZ0NvdW50OiAnZGVzYycgfSBhcyBhbnlcclxuICAgIGlmIChzb3J0ID09PSAnYmVzdC1yYXRpbmcnKSByZXR1cm4geyByYXRlOiAnZGVzYycsIHNob3BwaW5nQ291bnQ6ICdkZXNjJywgc3RvY2s6ICdkZXNjJywgbmFtZTogJ2FzYycgfVxyXG4gICAgaWYgKHNvcnQgPT09ICduZXdzJykgcmV0dXJuIHsgY3JlYXRlZEF0OiAnZGVzYycgfVxyXG4gICAgaWYgKHNvcnQgPT09ICdiaWdnZXN0LWRpc2NvdW50JylcclxuICAgICAgcmV0dXJuIHsgc3Vic2NyaWJlckRpc2NvdW50UGVyY2VudGFnZTogJ2Rlc2MnLCByYXRlOiAnZGVzYycsIHNob3BwaW5nQ291bnQ6ICdkZXNjJyB9IGFzIGFueVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBidWlsZExpbWl0UXVlcnkgPSAob3B0aW9uczogeyBwYWdlPzogbnVtYmVyOyBwZXJQYWdlPzogbnVtYmVyIH0pOiB7IGxpbWl0PzogbnVtYmVyOyBvZmZzZXQ/OiBudW1iZXIgfSA9PiB7XHJcbiAgICBjb25zdCBsaW1pdCA9IG9wdGlvbnM/LnBlclBhZ2UgfHwgMjBcclxuXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBsaW1pdCxcclxuICAgICAgb2Zmc2V0OiAoKG9wdGlvbnM/LnBhZ2UgfHwgMSkgLSAxKSAqIGxpbWl0LFxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBoYXNQcm9maWxlID0gKFxyXG4gICAgb3B0aW9uczogRmV0Y2hQcm9kdWN0c1BhcmFtczxUPixcclxuICApOiBvcHRpb25zIGlzIEZldGNoUHJvZHVjdHNPcHRpb25zICYge1xyXG4gICAgcHJvZmlsZTogRmV0Y2hQcm9kdWN0c01haW5QYXJhbXM8VD5bJ3Byb2ZpbGUnXVxyXG4gICAgZmlsdGVycz86IEZldGNoUHJvZHVjdHNGaWx0ZXJzICYgeyBjdXN0b21PcHRpb25zPzogbmV2ZXI7IHRhZ3M/OiBuZXZlciB9XHJcbiAgfSA9PiAncHJvZmlsZScgaW4gb3B0aW9uc1xyXG5cclxuICBwcml2YXRlIGhhc1Rlcm0gPSAoXHJcbiAgICBvcHRpb25zOiBGZXRjaFByb2R1Y3RzUGFyYW1zPFQ+LFxyXG4gICk6IG9wdGlvbnMgaXMgRmV0Y2hQcm9kdWN0c09wdGlvbnMgJiB7XHJcbiAgICB0ZXJtOiBGZXRjaFByb2R1Y3RzTWFpblBhcmFtczxUPlsndGVybSddXHJcbiAgICBmaWx0ZXJzPzogRmV0Y2hQcm9kdWN0c0ZpbHRlcnMgJiB7IGN1c3RvbU9wdGlvbnM/OiBuZXZlciB9XHJcbiAgfSA9PiAndGVybScgaW4gb3B0aW9uc1xyXG5cclxuICBwcml2YXRlIGhhc0NhdGVnb3J5ID0gKFxyXG4gICAgb3B0aW9uczogRmV0Y2hQcm9kdWN0c1BhcmFtczxUPixcclxuICApOiBvcHRpb25zIGlzIEZldGNoUHJvZHVjdHNPcHRpb25zICYge1xyXG4gICAgY2F0ZWdvcnk6IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+WydjYXRlZ29yeSddXHJcbiAgICBmaWx0ZXJzPzogRmV0Y2hQcm9kdWN0c0ZpbHRlcnMgJiB7IGN1c3RvbU9wdGlvbnM/OiBuZXZlciB9XHJcbiAgfSA9PiAnY2F0ZWdvcnknIGluIG9wdGlvbnNcclxufVxyXG4iXX0=
1
+ import { Inject, Injectable } from '@angular/core';
2
+ import { InvalidArgumentError, ProductsIndex, RoundProductPricesHelper, set, Shops, Where, } from '@infrab4a/connect';
3
+ import { CATEGORY_STRUCTURE, DEFAULT_SHOP } from '../../consts';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@infrab4a/connect";
6
+ export class CatalogService {
7
+ constructor(productRepository, productStockNotificationRepository, categoryRepository, categoryStructureAdapter, shop, productIndex) {
8
+ this.productRepository = productRepository;
9
+ this.productStockNotificationRepository = productStockNotificationRepository;
10
+ this.categoryRepository = categoryRepository;
11
+ this.categoryStructureAdapter = categoryStructureAdapter;
12
+ this.shop = shop;
13
+ this.productIndex = productIndex;
14
+ this.productsByTerm = {};
15
+ this.buildFilterQuery = ({ clubDiscount, brands, prices, gender, tags, rate, customOptions, }) => {
16
+ const filters = {};
17
+ if (clubDiscount?.length)
18
+ set(filters, 'price.subscriberDiscountPercentage', { operator: Where.IN, value: clubDiscount });
19
+ if (brands?.length)
20
+ filters.brand = { operator: Where.IN, value: brands };
21
+ if (gender?.length)
22
+ filters.gender = { operator: Where.IN, value: gender };
23
+ if (prices?.min || prices?.max)
24
+ set(filters, prices.subscriberPrice ? 'price.subscriberPrice' : 'price.price', [
25
+ ...(prices.min ? [{ operator: Where.GTE, value: Math.round(prices.min) }] : []),
26
+ ...(prices.max ? [{ operator: Where.LTE, value: Math.ceil(prices.max) }] : []),
27
+ ]);
28
+ if (rate)
29
+ filters.rate = { operator: Where.GTE, value: rate };
30
+ if (tags?.length)
31
+ filters.tags = { operator: Where.LIKE, value: tags };
32
+ if (customOptions?.length)
33
+ filters.filters = { operator: Where.LIKE, value: customOptions };
34
+ return filters;
35
+ };
36
+ this.buildSortQuery = (sort) => {
37
+ if (!sort || sort === 'most-relevant')
38
+ return {};
39
+ if (sort === 'best-sellers')
40
+ return {
41
+ shoppingCount: 'desc',
42
+ rate: 'desc',
43
+ stock: 'desc',
44
+ name: 'asc',
45
+ };
46
+ if (sort === 'biggest-price')
47
+ return { subscriberPrice: 'desc', rate: 'desc', shoppingCount: 'desc' };
48
+ if (sort === 'lowest-price')
49
+ return { subscriberPrice: 'asc', rate: 'desc', shoppingCount: 'desc' };
50
+ if (sort === 'best-rating')
51
+ return { rate: 'desc', shoppingCount: 'desc', stock: 'desc', name: 'asc' };
52
+ if (sort === 'news')
53
+ return { createdAt: 'desc' };
54
+ if (sort === 'biggest-discount')
55
+ return { subscriberDiscountPercentage: 'desc', rate: 'desc', shoppingCount: 'desc' };
56
+ };
57
+ this.buildLimitQuery = (options) => {
58
+ const limit = options?.perPage || 20;
59
+ return {
60
+ limit,
61
+ offset: ((options?.page || 1) - 1) * limit,
62
+ };
63
+ };
64
+ this.hasProfile = (options) => 'profile' in options;
65
+ this.hasTerm = (options) => 'term' in options;
66
+ this.hasCategory = (options) => 'category' in options;
67
+ }
68
+ async fetchProducts(options) {
69
+ const limits = this.buildLimitQuery(options);
70
+ if (this.hasProfile(options) && options.filters?.customOptions)
71
+ throw new InvalidArgumentError(`It couldn't filled customOptions when profile is given`);
72
+ if (this.hasProfile(options) && options.filters?.tags)
73
+ throw new InvalidArgumentError(`It couldn't filled tags when profile is given`);
74
+ if (this.hasTerm(options) && options.filters?.customOptions)
75
+ throw new InvalidArgumentError(`It couldn't filled customOptions when term is given`);
76
+ return await this.findCatalog(options, limits).then(({ data, count: total, maximum, minimal, distinct }) => ({
77
+ products: { data: data.map((product) => RoundProductPricesHelper.roundProductPrices(product)), total },
78
+ pages: Math.ceil(total / limits.limit),
79
+ prices: {
80
+ price: { min: +minimal?.price?.price?.toFixed(2), max: +maximum?.price?.price?.toFixed(2) },
81
+ subscriberPrice: {
82
+ min: +minimal?.price?.subscriberPrice?.toFixed(2),
83
+ max: +maximum?.price?.subscriberPrice?.toFixed(2),
84
+ },
85
+ },
86
+ brands: distinct?.brand,
87
+ }));
88
+ }
89
+ async addCustomerToStockNotification(shop, productId, name, email) {
90
+ return this.productStockNotificationRepository.addCustomerEmail(shop, productId, name, email);
91
+ }
92
+ async findCatalog(options, limits) {
93
+ if (this.hasTerm(options) && options.sort === 'most-relevant') {
94
+ const productsIds = await this.findCatalogIdsByElasticSearch(options.term);
95
+ return this.findCatalogAndSortByMostRevelantByTerm(productsIds, options, limits);
96
+ }
97
+ if (this.hasCategory(options) && options.sort === 'most-relevant') {
98
+ const mostRelevant = options.category.isWishlist ? [] : options.category.getMostRelevantByShop(this.shop);
99
+ const productsIds = await this.productRepository
100
+ .findCatalog({
101
+ fields: ['id'],
102
+ filters: {
103
+ ...(await this.buildMainFilter(options)),
104
+ ...this.buildFilterQuery(options?.filters || {}),
105
+ },
106
+ })
107
+ .then((products) => products.data.map((product) => product.id));
108
+ return this.findCatalogAndSortByMostRevelant(mostRelevant, productsIds, options, limits);
109
+ }
110
+ const repoParams = {
111
+ filters: {
112
+ ...(await this.buildMainFilter(options)),
113
+ ...this.buildFilterQuery(options?.filters || {}),
114
+ },
115
+ ...(options?.sort ? { orderBy: this.buildSortQuery(options?.sort) } : {}),
116
+ limits,
117
+ options: {
118
+ minimal: ['price'],
119
+ maximum: ['price'],
120
+ ...(!this.hasCategory(options) ? { distinct: ['brand'] } : {}),
121
+ },
122
+ };
123
+ if (['biggest-price', 'lowest-price', 'biggest-discount', 'best-rating'].includes(options.sort))
124
+ return this.productRepository.findCatalog(repoParams);
125
+ return this.productRepository.findCatalog(repoParams, options?.mainGender || this.shop === Shops.MENSMARKET ? 'male' : 'female');
126
+ }
127
+ async buildMainFilter({ category, profile, term, }) {
128
+ if (category)
129
+ return this.categoryStructureAdapter.buildProductFilterByCategory(category);
130
+ if (profile)
131
+ return { tags: { operator: Where.LIKE, value: profile } };
132
+ if (term)
133
+ return this.productIndex
134
+ .search(term, 999, this.shop)
135
+ .then((data) => ({ id: { operator: Where.IN, value: data.hits.map(({ _source }) => _source.id) } }));
136
+ }
137
+ async findCatalogAndSortByMostRevelant(mostRelevants, productIds, options, limits) {
138
+ const mostRelevantProductsIds = [...new Set(mostRelevants.concat(productIds))];
139
+ const totalResult = await this.productRepository.findCatalog({
140
+ filters: {
141
+ id: { operator: Where.IN, value: mostRelevantProductsIds },
142
+ ...this.buildFilterQuery(options?.filters || {}),
143
+ },
144
+ orderBy: this.buildSortQuery('best-sellers'),
145
+ options: {
146
+ minimal: ['price'],
147
+ maximum: ['price'],
148
+ distinct: ['brand'],
149
+ },
150
+ }, options?.mainGender || this.shop === Shops.MENSMARKET ? 'male' : 'female');
151
+ const mostRelevantWithouyStock = totalResult.data.filter((product) => mostRelevants.includes(product.id) && product.stock.quantity <= 0);
152
+ const firstProducts = totalResult.data
153
+ .filter((product) => mostRelevants.includes(product.id) && product.stock.quantity > 0)
154
+ .sort((a, b) => mostRelevants.indexOf(a.id) - mostRelevants.indexOf(b.id));
155
+ const lastProducts = totalResult.data
156
+ .filter((product) => !mostRelevants.includes(product.id))
157
+ .concat(mostRelevantWithouyStock);
158
+ const categoryMostRelevants = firstProducts.concat(lastProducts);
159
+ const resultFinal = categoryMostRelevants.slice(limits.offset, limits.offset + limits.limit);
160
+ return {
161
+ data: resultFinal,
162
+ count: totalResult.count,
163
+ maximum: totalResult.maximum,
164
+ minimal: totalResult.minimal,
165
+ distinct: totalResult.distinct,
166
+ };
167
+ }
168
+ async findCatalogAndSortByMostRevelantByTerm(productIds, options, limits) {
169
+ const totalResult = await this.productRepository.findCatalog({
170
+ fields: ['id', 'stock'],
171
+ filters: {
172
+ id: { operator: Where.IN, value: productIds },
173
+ ...this.buildFilterQuery(options?.filters || {}),
174
+ },
175
+ options: {
176
+ minimal: ['price'],
177
+ maximum: ['price'],
178
+ distinct: ['brand'],
179
+ },
180
+ }, options?.mainGender || this.shop === Shops.MENSMARKET ? 'male' : 'female');
181
+ const stockData = totalResult.data.filter((product) => product.stock.quantity > 0);
182
+ const stockOut = totalResult.data.filter((product) => product.stock.quantity <= 0);
183
+ const productIdsStock = productIds.filter((product) => stockData.some((result) => result.id == product));
184
+ const productIdsStockOut = productIds.filter((product) => stockOut.some((result) => result.id == product));
185
+ const limitedProductId = productIdsStock
186
+ .concat(productIdsStockOut)
187
+ .slice(limits.offset, limits.offset + limits.limit);
188
+ const orderedId = productIds.filter((product) => limitedProductId.includes(product));
189
+ const productResult = await this.productRepository.findCatalog({
190
+ filters: {
191
+ id: { operator: Where.IN, value: orderedId },
192
+ },
193
+ });
194
+ return {
195
+ data: limitedProductId.map((id) => productResult.data.find((product) => product.id === id)).filter(Boolean),
196
+ count: totalResult.count,
197
+ maximum: totalResult.maximum,
198
+ minimal: totalResult.minimal,
199
+ distinct: totalResult.distinct,
200
+ };
201
+ }
202
+ async findCatalogIdsByElasticSearch(term) {
203
+ if (this.productsByTerm[term])
204
+ return this.productsByTerm[term];
205
+ return (this.productsByTerm[term] = await this.productIndex
206
+ .search(term, 999, this.shop)
207
+ .then(({ hits: products }) => {
208
+ const withStock = products.filter(({ _source }) => _source.stock.quantity > 0);
209
+ const withOutStock = products.filter(({ _source }) => _source.stock.quantity <= 0);
210
+ const sorted = [...withStock, ...withOutStock];
211
+ return [...new Set(sorted.map(({ _source }) => _source.id))];
212
+ }));
213
+ }
214
+ }
215
+ CatalogService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.0", ngImport: i0, type: CatalogService, deps: [{ token: 'ProductRepository' }, { token: 'ProductStockNotificationRepository' }, { token: 'CategoryRepository' }, { token: CATEGORY_STRUCTURE }, { token: DEFAULT_SHOP }, { token: i1.ProductsIndex }], target: i0.ɵɵFactoryTarget.Injectable });
216
+ CatalogService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.1.0", ngImport: i0, type: CatalogService });
217
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.0", ngImport: i0, type: CatalogService, decorators: [{
218
+ type: Injectable
219
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
220
+ type: Inject,
221
+ args: ['ProductRepository']
222
+ }] }, { type: undefined, decorators: [{
223
+ type: Inject,
224
+ args: ['ProductStockNotificationRepository']
225
+ }] }, { type: undefined, decorators: [{
226
+ type: Inject,
227
+ args: ['CategoryRepository']
228
+ }] }, { type: undefined, decorators: [{
229
+ type: Inject,
230
+ args: [CATEGORY_STRUCTURE]
231
+ }] }, { type: i1.Shops, decorators: [{
232
+ type: Inject,
233
+ args: [DEFAULT_SHOP]
234
+ }] }, { type: i1.ProductsIndex }]; } });
235
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2F0YWxvZy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY29ubmVjdC1hbmd1bGFyL3NyYy9zZXJ2aWNlcy9jYXRhbG9nL2NhdGFsb2cuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUNsRCxPQUFPLEVBSUwsb0JBQW9CLEVBSXBCLGFBQWEsRUFLYix3QkFBd0IsRUFDeEIsR0FBRyxFQUNILEtBQUssRUFDTCxLQUFLLEdBQ04sTUFBTSxtQkFBbUIsQ0FBQTtBQUMxQixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsWUFBWSxFQUFFLE1BQU0sY0FBYyxDQUFBOzs7QUFzRC9ELE1BQU0sT0FBTyxjQUFjO0lBR3pCLFlBQ2dELGlCQUFvQyxFQUVqRSxrQ0FBc0UsRUFDeEMsa0JBQXNDLEVBQ3hDLHdCQUFrRCxFQUN4RCxJQUFXLEVBQ2pDLFlBQTJCO1FBTkUsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFtQjtRQUVqRSx1Q0FBa0MsR0FBbEMsa0NBQWtDLENBQW9DO1FBQ3hDLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBb0I7UUFDeEMsNkJBQXdCLEdBQXhCLHdCQUF3QixDQUEwQjtRQUN4RCxTQUFJLEdBQUosSUFBSSxDQUFPO1FBQ2pDLGlCQUFZLEdBQVosWUFBWSxDQUFlO1FBVHRDLG1CQUFjLEdBQTZCLEVBQUUsQ0FBQTtRQTRON0MscUJBQWdCLEdBQUcsQ0FBQyxFQUMxQixZQUFZLEVBQ1osTUFBTSxFQUNOLE1BQU0sRUFDTixNQUFNLEVBQ04sSUFBSSxFQUNKLElBQUksRUFDSixhQUFhLEdBQ1EsRUFBbUMsRUFBRTtZQUMxRCxNQUFNLE9BQU8sR0FBRyxFQUFxQyxDQUFBO1lBRXJELElBQUksWUFBWSxFQUFFLE1BQU07Z0JBQ3RCLEdBQUcsQ0FBQyxPQUFPLEVBQUUsb0NBQW9DLEVBQUUsRUFB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Q0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDLENBQUE7WUFDOUUsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsUUFBUSxJQUFJLENBQUMsQ0FBQyxDQUFBO1lBQ2xGLE1BQU0sTUFBTSxHQUFHLENBQUMsR0FBRyxTQUFTLEVBQUUsR0FBRyxZQUFZLENBQUMsQ0FBQTtZQUU5QyxPQUFPLENBQUMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUM5RCxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQ1AsQ0FBQzs7MkdBM05VLGNBQWMsa0JBSWYsbUJBQW1CLGFBQ25CLG9DQUFvQyxhQUVwQyxvQkFBb0IsYUFDcEIsa0JBQWtCLGFBQ2xCLFlBQVk7K0dBVFgsY0FBYzsyRkFBZCxjQUFjO2tCQUQxQixVQUFVOzswQkFLTixNQUFNOzJCQUFDLG1CQUFtQjs7MEJBQzFCLE1BQU07MkJBQUMsb0NBQW9DOzswQkFFM0MsTUFBTTsyQkFBQyxvQkFBb0I7OzBCQUMzQixNQUFNOzJCQUFDLGtCQUFrQjs7MEJBQ3pCLE1BQU07MkJBQUMsWUFBWSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnXG5pbXBvcnQge1xuICBDYXRlZ29yeSxcbiAgQ2F0ZWdvcnlSZXBvc2l0b3J5LFxuICBGaW5kUmVwb3NpdG9yeVBhcmFtcyxcbiAgSW52YWxpZEFyZ3VtZW50RXJyb3IsXG4gIFByb2R1Y3QsXG4gIFByb2R1Y3RHZW5kZXIsXG4gIFByb2R1Y3RSZXBvc2l0b3J5LFxuICBQcm9kdWN0c0luZGV4LFxuICBQcm9kdWN0U3RvY2tOb3RpZmljYXRpb25SZXBvc2l0b3J5LFxuICBSZXBvc2l0b3J5RmluZEZpZWx0ZXJzLFxuICBSZXBvc2l0b3J5RmluZFJlc3VsdCxcbiAgUmVwb3NpdG9yeU9yZGVyQnksXG4gIFJvdW5kUHJvZHVjdFByaWNlc0hlbHBlcixcbiAgc2V0LFxuICBTaG9wcyxcbiAgV2hlcmUsXG59IGZyb20gJ0BpbmZyYWI0YS9jb25uZWN0J1xuaW1wb3J0IHsgQ0FURUdPUllfU1RSVUNUVVJFLCBERUZBVUxUX1NIT1AgfSBmcm9tICcuLi8uLi9jb25zdHMnXG5pbXBvcnQgeyBDYXRlZ29yeVN0cnVjdHVyZUFkYXB0ZXIgfSBmcm9tICcuL2FkYXB0ZXJzJ1xuaW1wb3J0IHsgUHJvZHVjdFNvcnQgfSBmcm9tICcuL3R5cGVzL3Byb2R1Y3Qtc29ydC50eXBlJ1xuXG50eXBlIEZldGNoUHJvZHVjdHNGaWx0ZXJzID0ge1xuICBjbHViRGlzY291bnQ/OiBudW1iZXJbXVxuICBicmFuZHM/OiBzdHJpbmdbXVxuICBwcmljZXM/OiB7IG1pbj86IG51bWJlcjsgbWF4PzogbnVtYmVyOyBzdWJzY3JpYmVyUHJpY2U/OiBib29sZWFuIH1cbiAgZ2VuZGVyPzogUHJvZHVjdEdlbmRlcltdXG4gIHJhdGU/OiBudW1iZXJcbiAgY3VzdG9tT3B0aW9ucz86IHN0cmluZ1tdXG4gIHRhZ3M/OiBzdHJpbmdbXVxufVxuXG50eXBlIEZldGNoUHJvZHVjdHNPcHRpb25zID0ge1xuICBwYWdlPzogbnVtYmVyXG4gIHBlclBhZ2U/OiBudW1iZXJcbiAgc29ydD86IFByb2R1Y3RTb3J0XG4gIG1haW5HZW5kZXI/OiBQcm9kdWN0R2VuZGVyXG59XG5cbnR5cGUgRmV0Y2hQcm9kdWN0c01haW5QYXJhbXM8VCBleHRlbmRzIENhdGVnb3J5PiA9IHtcbiAgY2F0ZWdvcnk/OiBUXG4gIHByb2ZpbGU/OiBzdHJpbmdbXVxuICB0ZXJtPzogc3RyaW5nXG59XG5cbnR5cGUgRmV0Y2hQcm9kdWN0c1BhcmFtczxUIGV4dGVuZHMgQ2F0ZWdvcnk+ID0gRmV0Y2hQcm9kdWN0c09wdGlvbnMgJlxuICAoXG4gICAgfCB7XG4gICAgICAgIGNhdGVnb3J5OiBGZXRjaFByb2R1Y3RzTWFpblBhcmFtczxUPlsnY2F0ZWdvcnknXVxuICAgICAgICBmaWx0ZXJzPzogRmV0Y2hQcm9kdWN0c0ZpbHRlcnMgJiB7IGN1c3RvbU9wdGlvbnM/OiBuZXZlciB9XG4gICAgICB9XG4gICAgfCB7XG4gICAgICAgIHByb2ZpbGU6IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+Wydwcm9maWxlJ11cbiAgICAgICAgZmlsdGVycz86IEZldGNoUHJvZHVjdHNGaWx0ZXJzICYgeyBjdXN0b21PcHRpb25zPzogbmV2ZXI7IHRhZ3M/OiBuZXZlciB9XG4gICAgICB9XG4gICAgfCB7XG4gICAgICAgIHRlcm06IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+Wyd0ZXJtJ11cbiAgICAgICAgZmlsdGVycz86IEZldGNoUHJvZHVjdHNGaWx0ZXJzICYgeyBjdXN0b21PcHRpb25zPzogbmV2ZXIgfVxuICAgICAgfVxuICApXG5cbnR5cGUgRmV0Y2hQcm9kdWN0c1Jlc3BvbnNlID0ge1xuICBwcm9kdWN0czogeyBkYXRhOiBQcm9kdWN0W107IHRvdGFsOiBudW1iZXIgfVxuICBwYWdlczogbnVtYmVyXG4gIHByaWNlczoge1xuICAgIHByaWNlOiB7IG1pbjogbnVtYmVyOyBtYXg6IG51bWJlciB9XG4gICAgc3Vic2NyaWJlclByaWNlOiB7IG1pbjogbnVtYmVyOyBtYXg6IG51bWJlciB9XG4gIH1cbiAgYnJhbmRzPzogc3RyaW5nW11cbn1cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIENhdGFsb2dTZXJ2aWNlPFQgZXh0ZW5kcyBDYXRlZ29yeSA9IENhdGVnb3J5PiB7XG4gIHByaXZhdGUgcHJvZHVjdHNCeVRlcm06IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPiA9IHt9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQEluamVjdCgnUHJvZHVjdFJlcG9zaXRvcnknKSBwcml2YXRlIHJlYWRvbmx5IHByb2R1Y3RSZXBvc2l0b3J5OiBQcm9kdWN0UmVwb3NpdG9yeSxcbiAgICBASW5qZWN0KCdQcm9kdWN0U3RvY2tOb3RpZmljYXRpb25SZXBvc2l0b3J5JylcbiAgICBwcml2YXRlIHJlYWRvbmx5IHByb2R1Y3RTdG9ja05vdGlmaWNhdGlvblJlcG9zaXRvcnk6IFByb2R1Y3RTdG9ja05vdGlmaWNhdGlvblJlcG9zaXRvcnksXG4gICAgQEluamVjdCgnQ2F0ZWdvcnlSZXBvc2l0b3J5JykgcHJpdmF0ZSByZWFkb25seSBjYXRlZ29yeVJlcG9zaXRvcnk6IENhdGVnb3J5UmVwb3NpdG9yeSxcbiAgICBASW5qZWN0KENBVEVHT1JZX1NUUlVDVFVSRSkgcHJpdmF0ZSByZWFkb25seSBjYXRlZ29yeVN0cnVjdHVyZUFkYXB0ZXI6IENhdGVnb3J5U3RydWN0dXJlQWRhcHRlcixcbiAgICBASW5qZWN0KERFRkFVTFRfU0hPUCkgcHJpdmF0ZSByZWFkb25seSBzaG9wOiBTaG9wcyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHByb2R1Y3RJbmRleDogUHJvZHVjdHNJbmRleCxcbiAgKSB7fVxuXG4gIGFzeW5jIGZldGNoUHJvZHVjdHMob3B0aW9uczogRmV0Y2hQcm9kdWN0c1BhcmFtczxUPik6IFByb21pc2U8RmV0Y2hQcm9kdWN0c1Jlc3BvbnNlPiB7XG4gICAgY29uc3QgbGltaXRzID0gdGhpcy5idWlsZExpbWl0UXVlcnkob3B0aW9ucylcblxuICAgIGlmICh0aGlzLmhhc1Byb2ZpbGUob3B0aW9ucykgJiYgb3B0aW9ucy5maWx0ZXJzPy5jdXN0b21PcHRpb25zKVxuICAgICAgdGhyb3cgbmV3IEludmFsaWRBcmd1bWVudEVycm9yKGBJdCBjb3VsZG4ndCBmaWxsZWQgY3VzdG9tT3B0aW9ucyB3aGVuIHByb2ZpbGUgaXMgZ2l2ZW5gKVxuICAgIGlmICh0aGlzLmhhc1Byb2ZpbGUob3B0aW9ucykgJiYgb3B0aW9ucy5maWx0ZXJzPy50YWdzKVxuICAgICAgdGhyb3cgbmV3IEludmFsaWRBcmd1bWVudEVycm9yKGBJdCBjb3VsZG4ndCBmaWxsZWQgdGFncyB3aGVuIHByb2ZpbGUgaXMgZ2l2ZW5gKVxuICAgIGlmICh0aGlzLmhhc1Rlcm0ob3B0aW9ucykgJiYgb3B0aW9ucy5maWx0ZXJzPy5jdXN0b21PcHRpb25zKVxuICAgICAgdGhyb3cgbmV3IEludmFsaWRBcmd1bWVudEVycm9yKGBJdCBjb3VsZG4ndCBmaWxsZWQgY3VzdG9tT3B0aW9ucyB3aGVuIHRlcm0gaXMgZ2l2ZW5gKVxuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuZmluZENhdGFsb2cob3B0aW9ucywgbGltaXRzKS50aGVuKCh7IGRhdGEsIGNvdW50OiB0b3RhbCwgbWF4aW11bSwgbWluaW1hbCwgZGlzdGluY3QgfSkgPT4gKHtcbiAgICAgIHByb2R1Y3RzOiB7IGRhdGE6IGRhdGEubWFwKChwcm9kdWN0KSA9PiBSb3VuZFByb2R1Y3RQcmljZXNIZWxwZXIucm91bmRQcm9kdWN0UHJpY2VzKHByb2R1Y3QpKSwgdG90YWwgfSxcbiAgICAgIHBhZ2VzOiBNYXRoLmNlaWwodG90YWwgLyBsaW1pdHMubGltaXQpLFxuICAgICAgcHJpY2VzOiB7XG4gICAgICAgIHByaWNlOiB7IG1pbjogK21pbmltYWw/LnByaWNlPy5wcmljZT8udG9GaXhlZCgyKSwgbWF4OiArbWF4aW11bT8ucHJpY2U/LnByaWNlPy50b0ZpeGVkKDIpIH0sXG4gICAgICAgIHN1YnNjcmliZXJQcmljZToge1xuICAgICAgICAgIG1pbjogK21pbmltYWw/LnByaWNlPy5zdWJzY3JpYmVyUHJpY2U/LnRvRml4ZWQoMiksXG4gICAgICAgICAgbWF4OiArbWF4aW11bT8ucHJpY2U/LnN1YnNjcmliZXJQcmljZT8udG9GaXhlZCgyKSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBicmFuZHM6IGRpc3RpbmN0Py5icmFuZCxcbiAgICB9KSlcbiAgfVxuXG4gIGFzeW5jIGFkZEN1c3RvbWVyVG9TdG9ja05vdGlmaWNhdGlvbihzaG9wOiBTaG9wcywgcHJvZHVjdElkOiBzdHJpbmcsIG5hbWU6IHN0cmluZywgZW1haWw6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLnByb2R1Y3RTdG9ja05vdGlmaWNhdGlvblJlcG9zaXRvcnkuYWRkQ3VzdG9tZXJFbWFpbChzaG9wLCBwcm9kdWN0SWQsIG5hbWUsIGVtYWlsKVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBmaW5kQ2F0YWxvZyhcbiAgICBvcHRpb25zOiBGZXRjaFByb2R1Y3RzUGFyYW1zPFQ+LFxuICAgIGxpbWl0czoge1xuICAgICAgbGltaXQ/OiBudW1iZXJcbiAgICAgIG9mZnNldD86IG51bWJlclxuICAgIH0sXG4gICk6IFByb21pc2U8UmVwb3NpdG9yeUZpbmRSZXN1bHQ8UHJvZHVjdD4+IHtcbiAgICBpZiAodGhpcy5oYXNUZXJtKG9wdGlvbnMpICYmIG9wdGlvbnMuc29ydCA9PT0gJ21vc3QtcmVsZXZhbnQnKSB7XG4gICAgICBjb25zdCBwcm9kdWN0c0lkcyA9IGF3YWl0IHRoaXMuZmluZENhdGFsb2dJZHNCeUVsYXN0aWNTZWFyY2gob3B0aW9ucy50ZXJtKVxuXG4gICAgICByZXR1cm4gdGhpcy5maW5kQ2F0YWxvZ0FuZFNvcnRCeU1vc3RSZXZlbGFudEJ5VGVybShwcm9kdWN0c0lkcywgb3B0aW9ucywgbGltaXRzKVxuICAgIH1cblxuICAgIGlmICh0aGlzLmhhc0NhdGVnb3J5KG9wdGlvbnMpICYmIG9wdGlvbnMuc29ydCA9PT0gJ21vc3QtcmVsZXZhbnQnKSB7XG4gICAgICBjb25zdCBtb3N0UmVsZXZhbnQgPSBvcHRpb25zLmNhdGVnb3J5LmlzV2lzaGxpc3QgPyBbXSA6IG9wdGlvbnMuY2F0ZWdvcnkuZ2V0TW9zdFJlbGV2YW50QnlTaG9wKHRoaXMuc2hvcClcbiAgICAgIGNvbnN0IHByb2R1Y3RzSWRzID0gYXdhaXQgdGhpcy5wcm9kdWN0UmVwb3NpdG9yeVxuICAgICAgICAuZmluZENhdGFsb2coe1xuICAgICAgICAgIGZpZWxkczogWydpZCddLFxuICAgICAgICAgIGZpbHRlcnM6IHtcbiAgICAgICAgICAgIC4uLihhd2FpdCB0aGlzLmJ1aWxkTWFpbkZpbHRlcihvcHRpb25zKSksXG4gICAgICAgICAgICAuLi50aGlzLmJ1aWxkRmlsdGVyUXVlcnkob3B0aW9ucz8uZmlsdGVycyB8fCB7fSksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4oKHByb2R1Y3RzKSA9PiBwcm9kdWN0cy5kYXRhLm1hcCgocHJvZHVjdCkgPT4gcHJvZHVjdC5pZCkpXG5cbiAgICAgIHJldHVybiB0aGlzLmZpbmRDYXRhbG9nQW5kU29ydEJ5TW9zdFJldmVsYW50KG1vc3RSZWxldmFudCwgcHJvZHVjdHNJZHMsIG9wdGlvbnMsIGxpbWl0cylcbiAgICB9XG5cbiAgICBjb25zdCByZXBvUGFyYW1zOiBGaW5kUmVwb3NpdG9yeVBhcmFtczxQcm9kdWN0PiA9IHtcbiAgICAgIGZpbHRlcnM6IHtcbiAgICAgICAgLi4uKGF3YWl0IHRoaXMuYnVpbGRNYWluRmlsdGVyKG9wdGlvbnMpKSxcbiAgICAgICAgLi4udGhpcy5idWlsZEZpbHRlclF1ZXJ5KG9wdGlvbnM/LmZpbHRlcnMgfHwge30pLFxuICAgICAgfSxcbiAgICAgIC4uLihvcHRpb25zPy5zb3J0ID8geyBvcmRlckJ5OiB0aGlzLmJ1aWxkU29ydFF1ZXJ5KG9wdGlvbnM/LnNvcnQpIH0gOiB7fSksXG4gICAgICBsaW1pdHMsXG4gICAgICBvcHRpb25zOiB7XG4gICAgICAgIG1pbmltYWw6IFsncHJpY2UnXSxcbiAgICAgICAgbWF4aW11bTogWydwcmljZSddLFxuICAgICAgICAuLi4oIXRoaXMuaGFzQ2F0ZWdvcnkob3B0aW9ucykgPyB7IGRpc3RpbmN0OiBbJ2JyYW5kJ10gfSA6IHt9KSxcbiAgICAgIH0sXG4gICAgfVxuXG4gICAgaWYgKFsnYmlnZ2VzdC1wcmljZScsICdsb3dlc3QtcHJpY2UnLCAnYmlnZ2VzdC1kaXNjb3VudCcsICdiZXN0LXJhdGluZyddLmluY2x1ZGVzKG9wdGlvbnMuc29ydCkpXG4gICAgICByZXR1cm4gdGhpcy5wcm9kdWN0UmVwb3NpdG9yeS5maW5kQ2F0YWxvZyhyZXBvUGFyYW1zKVxuXG4gICAgcmV0dXJuIHRoaXMucHJvZHVjdFJlcG9zaXRvcnkuZmluZENhdGFsb2coXG4gICAgICByZXBvUGFyYW1zLFxuICAgICAgb3B0aW9ucz8ubWFpbkdlbmRlciB8fCB0aGlzLnNob3AgPT09IFNob3BzLk1FTlNNQVJLRVQgPyAnbWFsZScgOiAnZmVtYWxlJyxcbiAgICApXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGJ1aWxkTWFpbkZpbHRlcih7XG4gICAgY2F0ZWdvcnksXG4gICAgcHJvZmlsZSxcbiAgICB0ZXJtLFxuICB9OiBGZXRjaFByb2R1Y3RzTWFpblBhcmFtczxUPik6IFByb21pc2U8UmVwb3NpdG9yeUZpbmRGaWVsdGVyczxQcm9kdWN0Pj4ge1xuICAgIGlmIChjYXRlZ29yeSkgcmV0dXJuIHRoaXMuY2F0ZWdvcnlTdHJ1Y3R1cmVBZGFwdGVyLmJ1aWxkUHJvZHVjdEZpbHRlckJ5Q2F0ZWdvcnkoY2F0ZWdvcnkpXG4gICAgaWYgKHByb2ZpbGUpIHJldHVybiB7IHRhZ3M6IHsgb3BlcmF0b3I6IFdoZXJlLkxJS0UsIHZhbHVlOiBwcm9maWxlIH0gfVxuICAgIGlmICh0ZXJtKVxuICAgICAgcmV0dXJuIHRoaXMucHJvZHVjdEluZGV4XG4gICAgICAgIC5zZWFyY2godGVybSwgOTk5LCB0aGlzLnNob3ApXG4gICAgICAgIC50aGVuKChkYXRhKSA9PiAoeyBpZDogeyBvcGVyYXRvcjogV2hlcmUuSU4sIHZhbHVlOiBkYXRhLmhpdHMubWFwKCh7IF9zb3VyY2UgfSkgPT4gX3NvdXJjZS5pZCkgfSB9KSlcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZmluZENhdGFsb2dBbmRTb3J0QnlNb3N0UmV2ZWxhbnQoXG4gICAgbW9zdFJlbGV2YW50czogc3RyaW5nW10sXG4gICAgcHJvZHVjdElkczogc3RyaW5nW10sXG4gICAgb3B0aW9uczogT21pdDxGZXRjaFByb2R1Y3RzT3B0aW9ucywgJ3NvcnQnPiAmIHtcbiAgICAgIHRlcm0/OiBGZXRjaFByb2R1Y3RzTWFpblBhcmFtczxUPlsndGVybSddXG4gICAgICBmaWx0ZXJzPzogRmV0Y2hQcm9kdWN0c0ZpbHRlcnMgJiB7IGN1c3RvbU9wdGlvbnM/OiBuZXZlciB9XG4gICAgfSxcbiAgICBsaW1pdHM6IHtcbiAgICAgIGxpbWl0PzogbnVtYmVyXG4gICAgICBvZmZzZXQ/OiBudW1iZXJcbiAgICB9LFxuICApOiBQcm9taXNlPFJlcG9zaXRvcnlGaW5kUmVzdWx0PFByb2R1Y3Q+PiB7XG4gICAgY29uc3QgbW9zdFJlbGV2YW50UHJvZHVjdHNJZHMgPSBbLi4ubmV3IFNldChtb3N0UmVsZXZhbnRzLmNvbmNhdChwcm9kdWN0SWRzKSldXG4gICAgY29uc3QgdG90YWxSZXN1bHQgPSBhd2FpdCB0aGlzLnByb2R1Y3RSZXBvc2l0b3J5LmZpbmRDYXRhbG9nKFxuICAgICAge1xuICAgICAgICBmaWx0ZXJzOiB7XG4gICAgICAgICAgaWQ6IHsgb3BlcmF0b3I6IFdoZXJlLklOLCB2YWx1ZTogbW9zdFJlbGV2YW50UHJvZHVjdHNJZHMgfSxcbiAgICAgICAgICAuLi50aGlzLmJ1aWxkRmlsdGVyUXVlcnkob3B0aW9ucz8uZmlsdGVycyB8fCB7fSksXG4gICAgICAgIH0sXG4gICAgICAgIG9yZGVyQnk6IHRoaXMuYnVpbGRTb3J0UXVlcnkoJ2Jlc3Qtc2VsbGVycycpLFxuICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgbWluaW1hbDogWydwcmljZSddLFxuICAgICAgICAgIG1heGltdW06IFsncHJpY2UnXSxcbiAgICAgICAgICBkaXN0aW5jdDogWydicmFuZCddLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIG9wdGlvbnM/Lm1haW5HZW5kZXIgfHwgdGhpcy5zaG9wID09PSBTaG9wcy5NRU5TTUFSS0VUID8gJ21hbGUnIDogJ2ZlbWFsZScsXG4gICAgKVxuXG4gICAgY29uc3QgbW9zdFJlbGV2YW50V2l0aG91eVN0b2NrID0gdG90YWxSZXN1bHQuZGF0YS5maWx0ZXIoXG4gICAgICAocHJvZHVjdCkgPT4gbW9zdFJlbGV2YW50cy5pbmNsdWRlcyhwcm9kdWN0LmlkKSAmJiBwcm9kdWN0LnN0b2NrLnF1YW50aXR5IDw9IDAsXG4gICAgKVxuICAgIGNvbnN0IGZpcnN0UHJvZHVjdHMgPSB0b3RhbFJlc3VsdC5kYXRhXG4gICAgICAuZmlsdGVyKChwcm9kdWN0KSA9PiBtb3N0UmVsZXZhbnRzLmluY2x1ZGVzKHByb2R1Y3QuaWQpICYmIHByb2R1Y3Quc3RvY2sucXVhbnRpdHkgPiAwKVxuICAgICAgLnNvcnQoKGEsIGIpID0+IG1vc3RSZWxldmFudHMuaW5kZXhPZihhLmlkKSAtIG1vc3RSZWxldmFudHMuaW5kZXhPZihiLmlkKSlcbiAgICBjb25zdCBsYXN0UHJvZHVjdHMgPSB0b3RhbFJlc3VsdC5kYXRhXG4gICAgICAuZmlsdGVyKChwcm9kdWN0KSA9PiAhbW9zdFJlbGV2YW50cy5pbmNsdWRlcyhwcm9kdWN0LmlkKSlcbiAgICAgIC5jb25jYXQobW9zdFJlbGV2YW50V2l0aG91eVN0b2NrKVxuICAgIGNvbnN0IGNhdGVnb3J5TW9zdFJlbGV2YW50cyA9IGZpcnN0UHJvZHVjdHMuY29uY2F0KGxhc3RQcm9kdWN0cylcbiAgICBjb25zdCByZXN1bHRGaW5hbCA9IGNhdGVnb3J5TW9zdFJlbGV2YW50cy5zbGljZShsaW1pdHMub2Zmc2V0LCBsaW1pdHMub2Zmc2V0ICsgbGltaXRzLmxpbWl0KVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGE6IHJlc3VsdEZpbmFsLFxuICAgICAgY291bnQ6IHRvdGFsUmVzdWx0LmNvdW50LFxuICAgICAgbWF4aW11bTogdG90YWxSZXN1bHQubWF4aW11bSxcbiAgICAgIG1pbmltYWw6IHRvdGFsUmVzdWx0Lm1pbmltYWwsXG4gICAgICBkaXN0aW5jdDogdG90YWxSZXN1bHQuZGlzdGluY3QsXG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBmaW5kQ2F0YWxvZ0FuZFNvcnRCeU1vc3RSZXZlbGFudEJ5VGVybShcbiAgICBwcm9kdWN0SWRzOiBzdHJpbmdbXSxcbiAgICBvcHRpb25zOiBPbWl0PEZldGNoUHJvZHVjdHNPcHRpb25zLCAnc29ydCc+ICYge1xuICAgICAgdGVybT86IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+Wyd0ZXJtJ11cbiAgICAgIGZpbHRlcnM/OiBGZXRjaFByb2R1Y3RzRmlsdGVycyAmIHsgY3VzdG9tT3B0aW9ucz86IG5ldmVyIH1cbiAgICB9LFxuICAgIGxpbWl0czoge1xuICAgICAgbGltaXQ/OiBudW1iZXJcbiAgICAgIG9mZnNldD86IG51bWJlclxuICAgIH0sXG4gICk6IFByb21pc2U8UmVwb3NpdG9yeUZpbmRSZXN1bHQ8UHJvZHVjdD4+IHtcbiAgICBjb25zdCB0b3RhbFJlc3VsdCA9IGF3YWl0IHRoaXMucHJvZHVjdFJlcG9zaXRvcnkuZmluZENhdGFsb2coXG4gICAgICB7XG4gICAgICAgIGZpZWxkczogWydpZCcsICdzdG9jayddLFxuICAgICAgICBmaWx0ZXJzOiB7XG4gICAgICAgICAgaWQ6IHsgb3BlcmF0b3I6IFdoZXJlLklOLCB2YWx1ZTogcHJvZHVjdElkcyB9LFxuICAgICAgICAgIC4uLnRoaXMuYnVpbGRGaWx0ZXJRdWVyeShvcHRpb25zPy5maWx0ZXJzIHx8IHt9KSxcbiAgICAgICAgfSxcbiAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgIG1pbmltYWw6IFsncHJpY2UnXSxcbiAgICAgICAgICBtYXhpbXVtOiBbJ3ByaWNlJ10sXG4gICAgICAgICAgZGlzdGluY3Q6IFsnYnJhbmQnXSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBvcHRpb25zPy5tYWluR2VuZGVyIHx8IHRoaXMuc2hvcCA9PT0gU2hvcHMuTUVOU01BUktFVCA/ICdtYWxlJyA6ICdmZW1hbGUnLFxuICAgIClcblxuICAgIGNvbnN0IHN0b2NrRGF0YSA9IHRvdGFsUmVzdWx0LmRhdGEuZmlsdGVyKChwcm9kdWN0KSA9PiBwcm9kdWN0LnN0b2NrLnF1YW50aXR5ID4gMClcbiAgICBjb25zdCBzdG9ja091dCA9IHRvdGFsUmVzdWx0LmRhdGEuZmlsdGVyKChwcm9kdWN0KSA9PiBwcm9kdWN0LnN0b2NrLnF1YW50aXR5IDw9IDApXG4gICAgY29uc3QgcHJvZHVjdElkc1N0b2NrID0gcHJvZHVjdElkcy5maWx0ZXIoKHByb2R1Y3QpID0+IHN0b2NrRGF0YS5zb21lKChyZXN1bHQpID0+IHJlc3VsdC5pZCA9PSBwcm9kdWN0KSlcbiAgICBjb25zdCBwcm9kdWN0SWRzU3RvY2tPdXQgPSBwcm9kdWN0SWRzLmZpbHRlcigocHJvZHVjdCkgPT4gc3RvY2tPdXQuc29tZSgocmVzdWx0KSA9PiByZXN1bHQuaWQgPT0gcHJvZHVjdCkpXG5cbiAgICBjb25zdCBsaW1pdGVkUHJvZHVjdElkID0gcHJvZHVjdElkc1N0b2NrXG4gICAgICAuY29uY2F0KHByb2R1Y3RJZHNTdG9ja091dClcbiAgICAgIC5zbGljZShsaW1pdHMub2Zmc2V0LCBsaW1pdHMub2Zmc2V0ICsgbGltaXRzLmxpbWl0KVxuXG4gICAgY29uc3Qgb3JkZXJlZElkID0gcHJvZHVjdElkcy5maWx0ZXIoKHByb2R1Y3QpID0+IGxpbWl0ZWRQcm9kdWN0SWQuaW5jbHVkZXMocHJvZHVjdCkpXG4gICAgY29uc3QgcHJvZHVjdFJlc3VsdCA9IGF3YWl0IHRoaXMucHJvZHVjdFJlcG9zaXRvcnkuZmluZENhdGFsb2coe1xuICAgICAgZmlsdGVyczoge1xuICAgICAgICBpZDogeyBvcGVyYXRvcjogV2hlcmUuSU4sIHZhbHVlOiBvcmRlcmVkSWQgfSxcbiAgICAgIH0sXG4gICAgfSlcblxuICAgIHJldHVybiB7XG4gICAgICBkYXRhOiBsaW1pdGVkUHJvZHVjdElkLm1hcCgoaWQpID0+IHByb2R1Y3RSZXN1bHQuZGF0YS5maW5kKChwcm9kdWN0KSA9PiBwcm9kdWN0LmlkID09PSBpZCkpLmZpbHRlcihCb29sZWFuKSxcbiAgICAgIGNvdW50OiB0b3RhbFJlc3VsdC5jb3VudCxcbiAgICAgIG1heGltdW06IHRvdGFsUmVzdWx0Lm1heGltdW0sXG4gICAgICBtaW5pbWFsOiB0b3RhbFJlc3VsdC5taW5pbWFsLFxuICAgICAgZGlzdGluY3Q6IHRvdGFsUmVzdWx0LmRpc3RpbmN0LFxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZmluZENhdGFsb2dJZHNCeUVsYXN0aWNTZWFyY2godGVybTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIGlmICh0aGlzLnByb2R1Y3RzQnlUZXJtW3Rlcm1dKSByZXR1cm4gdGhpcy5wcm9kdWN0c0J5VGVybVt0ZXJtXVxuXG4gICAgcmV0dXJuICh0aGlzLnByb2R1Y3RzQnlUZXJtW3Rlcm1dID0gYXdhaXQgdGhpcy5wcm9kdWN0SW5kZXhcbiAgICAgIC5zZWFyY2godGVybSwgOTk5LCB0aGlzLnNob3ApXG4gICAgICAudGhlbigoeyBoaXRzOiBwcm9kdWN0cyB9KSA9PiB7XG4gICAgICAgIGNvbnN0IHdpdGhTdG9jayA9IHByb2R1Y3RzLmZpbHRlcigoeyBfc291cmNlIH0pID0+IF9zb3VyY2Uuc3RvY2sucXVhbnRpdHkgPiAwKVxuICAgICAgICBjb25zdCB3aXRoT3V0U3RvY2sgPSBwcm9kdWN0cy5maWx0ZXIoKHsgX3NvdXJjZSB9KSA9PiBfc291cmNlLnN0b2NrLnF1YW50aXR5IDw9IDApXG4gICAgICAgIGNvbnN0IHNvcnRlZCA9IFsuLi53aXRoU3RvY2ssIC4uLndpdGhPdXRTdG9ja11cblxuICAgICAgICByZXR1cm4gWy4uLm5ldyBTZXQoc29ydGVkLm1hcCgoeyBfc291cmNlIH0pID0+IF9zb3VyY2UuaWQpKV1cbiAgICAgIH0pKVxuICB9XG5cbiAgcHJpdmF0ZSBidWlsZEZpbHRlclF1ZXJ5ID0gKHtcbiAgICBjbHViRGlzY291bnQsXG4gICAgYnJhbmRzLFxuICAgIHByaWNlcyxcbiAgICBnZW5kZXIsXG4gICAgdGFncyxcbiAgICByYXRlLFxuICAgIGN1c3RvbU9wdGlvbnMsXG4gIH06IEZldGNoUHJvZHVjdHNGaWx0ZXJzKTogUmVwb3NpdG9yeUZpbmRGaWVsdGVyczxQcm9kdWN0PiA9PiB7XG4gICAgY29uc3QgZmlsdGVycyA9IHt9IGFzIFJlcG9zaXRvcnlGaW5kRmllbHRlcnM8UHJvZHVjdD5cblxuICAgIGlmIChjbHViRGlzY291bnQ/Lmxlbmd0aClcbiAgICAgIHNldChmaWx0ZXJzLCAncHJpY2Uuc3Vic2NyaWJlckRpc2NvdW50UGVyY2VudGFnZScsIHsgb3BlcmF0b3I6IFdoZXJlLklOLCB2YWx1ZTogY2x1YkRpc2NvdW50IH0pXG4gICAgaWYgKGJyYW5kcz8ubGVuZ3RoKSBmaWx0ZXJzLmJyYW5kID0geyBvcGVyYXRvcjogV2hlcmUuSU4sIHZhbHVlOiBicmFuZHMgfVxuICAgIGlmIChnZW5kZXI/Lmxlbmd0aCkgZmlsdGVycy5nZW5kZXIgPSB7IG9wZXJhdG9yOiBXaGVyZS5JTiwgdmFsdWU6IGdlbmRlciB9XG4gICAgaWYgKHByaWNlcz8ubWluIHx8IHByaWNlcz8ubWF4KVxuICAgICAgc2V0KGZpbHRlcnMsIHByaWNlcy5zdWJzY3JpYmVyUHJpY2UgPyAncHJpY2Uuc3Vic2NyaWJlclByaWNlJyA6ICdwcmljZS5wcmljZScsIFtcbiAgICAgICAgLi4uKHByaWNlcy5taW4gPyBbeyBvcGVyYXRvcjogV2hlcmUuR1RFLCB2YWx1ZTogTWF0aC5yb3VuZChwcmljZXMubWluKSB9XSA6IFtdKSxcbiAgICAgICAgLi4uKHByaWNlcy5tYXggPyBbeyBvcGVyYXRvcjogV2hlcmUuTFRFLCB2YWx1ZTogTWF0aC5jZWlsKHByaWNlcy5tYXgpIH1dIDogW10pLFxuICAgICAgXSlcbiAgICBpZiAocmF0ZSkgZmlsdGVycy5yYXRlID0geyBvcGVyYXRvcjogV2hlcmUuR1RFLCB2YWx1ZTogcmF0ZSB9XG4gICAgaWYgKHRhZ3M/Lmxlbmd0aCkgZmlsdGVycy50YWdzID0geyBvcGVyYXRvcjogV2hlcmUuTElLRSwgdmFsdWU6IHRhZ3MgfVxuICAgIGlmIChjdXN0b21PcHRpb25zPy5sZW5ndGgpIGZpbHRlcnMuZmlsdGVycyA9IHsgb3BlcmF0b3I6IFdoZXJlLkxJS0UsIHZhbHVlOiBjdXN0b21PcHRpb25zIH1cblxuICAgIHJldHVybiBmaWx0ZXJzXG4gIH1cblxuICBwcml2YXRlIGJ1aWxkU29ydFF1ZXJ5ID0gKHNvcnQ6IFByb2R1Y3RTb3J0KTogUmVwb3NpdG9yeU9yZGVyQnk8UHJvZHVjdD4gPT4ge1xuICAgIGlmICghc29ydCB8fCBzb3J0ID09PSAnbW9zdC1yZWxldmFudCcpIHJldHVybiB7fVxuXG4gICAgaWYgKHNvcnQgPT09ICdiZXN0LXNlbGxlcnMnKVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc2hvcHBpbmdDb3VudDogJ2Rlc2MnLFxuICAgICAgICByYXRlOiAnZGVzYycsXG4gICAgICAgIHN0b2NrOiAnZGVzYycsXG4gICAgICAgIG5hbWU6ICdhc2MnLFxuICAgICAgfVxuICAgIGlmIChzb3J0ID09PSAnYmlnZ2VzdC1wcmljZScpIHJldHVybiB7IHN1YnNjcmliZXJQcmljZTogJ2Rlc2MnLCByYXRlOiAnZGVzYycsIHNob3BwaW5nQ291bnQ6ICdkZXNjJyB9IGFzIGFueVxuICAgIGlmIChzb3J0ID09PSAnbG93ZXN0LXByaWNlJykgcmV0dXJuIHsgc3Vic2NyaWJlclByaWNlOiAnYXNjJywgcmF0ZTogJ2Rlc2MnLCBzaG9wcGluZ0NvdW50OiAnZGVzYycgfSBhcyBhbnlcbiAgICBpZiAoc29ydCA9PT0gJ2Jlc3QtcmF0aW5nJykgcmV0dXJuIHsgcmF0ZTogJ2Rlc2MnLCBzaG9wcGluZ0NvdW50OiAnZGVzYycsIHN0b2NrOiAnZGVzYycsIG5hbWU6ICdhc2MnIH1cbiAgICBpZiAoc29ydCA9PT0gJ25ld3MnKSByZXR1cm4geyBjcmVhdGVkQXQ6ICdkZXNjJyB9XG4gICAgaWYgKHNvcnQgPT09ICdiaWdnZXN0LWRpc2NvdW50JylcbiAgICAgIHJldHVybiB7IHN1YnNjcmliZXJEaXNjb3VudFBlcmNlbnRhZ2U6ICdkZXNjJywgcmF0ZTogJ2Rlc2MnLCBzaG9wcGluZ0NvdW50OiAnZGVzYycgfSBhcyBhbnlcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRMaW1pdFF1ZXJ5ID0gKG9wdGlvbnM6IHsgcGFnZT86IG51bWJlcjsgcGVyUGFnZT86IG51bWJlciB9KTogeyBsaW1pdD86IG51bWJlcjsgb2Zmc2V0PzogbnVtYmVyIH0gPT4ge1xuICAgIGNvbnN0IGxpbWl0ID0gb3B0aW9ucz8ucGVyUGFnZSB8fCAyMFxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGxpbWl0LFxuICAgICAgb2Zmc2V0OiAoKG9wdGlvbnM/LnBhZ2UgfHwgMSkgLSAxKSAqIGxpbWl0LFxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaGFzUHJvZmlsZSA9IChcbiAgICBvcHRpb25zOiBGZXRjaFByb2R1Y3RzUGFyYW1zPFQ+LFxuICApOiBvcHRpb25zIGlzIEZldGNoUHJvZHVjdHNPcHRpb25zICYge1xuICAgIHByb2ZpbGU6IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+Wydwcm9maWxlJ11cbiAgICBmaWx0ZXJzPzogRmV0Y2hQcm9kdWN0c0ZpbHRlcnMgJiB7IGN1c3RvbU9wdGlvbnM/OiBuZXZlcjsgdGFncz86IG5ldmVyIH1cbiAgfSA9PiAncHJvZmlsZScgaW4gb3B0aW9uc1xuXG4gIHByaXZhdGUgaGFzVGVybSA9IChcbiAgICBvcHRpb25zOiBGZXRjaFByb2R1Y3RzUGFyYW1zPFQ+LFxuICApOiBvcHRpb25zIGlzIEZldGNoUHJvZHVjdHNPcHRpb25zICYge1xuICAgIHRlcm06IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+Wyd0ZXJtJ11cbiAgICBmaWx0ZXJzPzogRmV0Y2hQcm9kdWN0c0ZpbHRlcnMgJiB7IGN1c3RvbU9wdGlvbnM/OiBuZXZlciB9XG4gIH0gPT4gJ3Rlcm0nIGluIG9wdGlvbnNcblxuICBwcml2YXRlIGhhc0NhdGVnb3J5ID0gKFxuICAgIG9wdGlvbnM6IEZldGNoUHJvZHVjdHNQYXJhbXM8VD4sXG4gICk6IG9wdGlvbnMgaXMgRmV0Y2hQcm9kdWN0c09wdGlvbnMgJiB7XG4gICAgY2F0ZWdvcnk6IEZldGNoUHJvZHVjdHNNYWluUGFyYW1zPFQ+WydjYXRlZ29yeSddXG4gICAgZmlsdGVycz86IEZldGNoUHJvZHVjdHNGaWx0ZXJzICYgeyBjdXN0b21PcHRpb25zPzogbmV2ZXIgfVxuICB9ID0+ICdjYXRlZ29yeScgaW4gb3B0aW9uc1xufVxuIl19