@rudderstack/integrations-lib 0.2.33 → 0.2.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/sdks/sfmc/index.d.ts +26 -3
- package/build/sdks/sfmc/index.d.ts.map +1 -1
- package/build/sdks/sfmc/index.js +108 -16
- package/build/sdks/sfmc/type.d.ts +44 -24
- package/build/sdks/sfmc/type.d.ts.map +1 -1
- package/build/sdks/sfmc/type.js +1 -1
- package/build/utils/batch-processing.bench.d.ts +2 -0
- package/build/utils/batch-processing.bench.d.ts.map +1 -0
- package/build/utils/batch-processing.bench.js +96 -0
- package/build/utils/batch-processing.d.ts +75 -83
- package/build/utils/batch-processing.d.ts.map +1 -1
- package/build/utils/batch-processing.js +240 -161
- package/build/utils/benchmark.d.ts +180 -0
- package/build/utils/benchmark.d.ts.map +1 -0
- package/build/utils/benchmark.js +288 -0
- package/package.json +1 -1
|
@@ -6,9 +6,11 @@ exports.filterInBatches = filterInBatches;
|
|
|
6
6
|
exports.groupByInBatches = groupByInBatches;
|
|
7
7
|
exports.reduceInBatches = reduceInBatches;
|
|
8
8
|
exports.flatMapInBatches = flatMapInBatches;
|
|
9
|
+
exports.forEachInBatches = forEachInBatches;
|
|
9
10
|
// Default configuration values (internal)
|
|
10
11
|
let defaultBatchSize = 10;
|
|
11
12
|
let defaultYieldThreshold = 10;
|
|
13
|
+
let defaultSequentialProcessing = true;
|
|
12
14
|
/**
|
|
13
15
|
* Configure global defaults for batch processing operations
|
|
14
16
|
*
|
|
@@ -23,6 +25,9 @@ let defaultYieldThreshold = 10;
|
|
|
23
25
|
* // Set only batch size
|
|
24
26
|
* configureBatchProcessingDefaults({ batchSize: 50 });
|
|
25
27
|
*
|
|
28
|
+
* // Enable concurrent processing within batches
|
|
29
|
+
* configureBatchProcessingDefaults({ sequentialProcessing: false });
|
|
30
|
+
*
|
|
26
31
|
* // Get current configuration
|
|
27
32
|
* const currentConfig = configureBatchProcessingDefaults();
|
|
28
33
|
* ```
|
|
@@ -41,10 +46,14 @@ function configureBatchProcessingDefaults(config) {
|
|
|
41
46
|
}
|
|
42
47
|
defaultYieldThreshold = config.yieldThreshold;
|
|
43
48
|
}
|
|
49
|
+
if (config.sequentialProcessing !== undefined) {
|
|
50
|
+
defaultSequentialProcessing = Boolean(config.sequentialProcessing);
|
|
51
|
+
}
|
|
44
52
|
}
|
|
45
53
|
return {
|
|
46
54
|
batchSize: defaultBatchSize,
|
|
47
55
|
yieldThreshold: defaultYieldThreshold,
|
|
56
|
+
sequentialProcessing: defaultSequentialProcessing,
|
|
48
57
|
};
|
|
49
58
|
}
|
|
50
59
|
/**
|
|
@@ -68,6 +77,57 @@ function defer(startTime, yieldThreshold) {
|
|
|
68
77
|
// Otherwise continue immediately
|
|
69
78
|
return Promise.resolve(false);
|
|
70
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Helper to get batch processing options with defaults applied
|
|
82
|
+
* @param options - User provided options
|
|
83
|
+
* @returns Options with defaults applied
|
|
84
|
+
* @internal
|
|
85
|
+
*/
|
|
86
|
+
function getOptions(options) {
|
|
87
|
+
const batchSize = options?.batchSize ?? defaultBatchSize;
|
|
88
|
+
const yieldThreshold = options?.yieldThreshold ?? defaultYieldThreshold;
|
|
89
|
+
const sequentialProcessing = options?.sequentialProcessing ?? defaultSequentialProcessing;
|
|
90
|
+
if (!Number.isInteger(batchSize) || batchSize <= 0) {
|
|
91
|
+
throw new Error('batchSize must be a positive integer');
|
|
92
|
+
}
|
|
93
|
+
if (!Number.isInteger(yieldThreshold) || yieldThreshold < 0) {
|
|
94
|
+
throw new Error('yieldThreshold must be a non-negative integer');
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
batchSize,
|
|
98
|
+
yieldThreshold,
|
|
99
|
+
sequentialProcessing,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Helper to process an array in batches, yielding as needed.
|
|
104
|
+
* @param items - The array to process
|
|
105
|
+
* @param options - Batch processing options
|
|
106
|
+
* @param batchHandler - Function to handle each batch: (batch, batchStartIndex) => Promise<any>
|
|
107
|
+
* @returns Promise<void>
|
|
108
|
+
*/
|
|
109
|
+
async function processInBatches(items, options, batchHandler) {
|
|
110
|
+
let i = 0;
|
|
111
|
+
let startTime = Date.now();
|
|
112
|
+
const { batchSize } = options;
|
|
113
|
+
const n = items.length;
|
|
114
|
+
// Allocate a single batch array and reuses it for all batches
|
|
115
|
+
const batch = Array(batchSize);
|
|
116
|
+
while (i < n) {
|
|
117
|
+
const len = Math.min(batchSize, n - i);
|
|
118
|
+
for (let j = 0; j < len; j += 1) {
|
|
119
|
+
batch[j] = items[i + j];
|
|
120
|
+
}
|
|
121
|
+
batch.length = len;
|
|
122
|
+
// eslint-disable-next-line no-await-in-loop
|
|
123
|
+
await batchHandler(batch, i);
|
|
124
|
+
i += batchSize;
|
|
125
|
+
// eslint-disable-next-line no-await-in-loop
|
|
126
|
+
const didYield = await defer(startTime, options.yieldThreshold);
|
|
127
|
+
if (didYield)
|
|
128
|
+
startTime = Date.now();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
71
131
|
/**
|
|
72
132
|
* Maps over an array in batches to avoid blocking the event loop.
|
|
73
133
|
* Processes items in chunks and yields control back to the event loop between batches
|
|
@@ -77,40 +137,40 @@ function defer(startTime, yieldThreshold) {
|
|
|
77
137
|
* @template R - The type of items in the result array
|
|
78
138
|
* @param items - The array to map over
|
|
79
139
|
* @param mapFn - The mapping function to apply to each item. Receives the item and its index.
|
|
80
|
-
* @param
|
|
81
|
-
* @param yieldThreshold - Time threshold in milliseconds before yielding control (default: @see defaultYieldThreshold)
|
|
140
|
+
* @param options - Batch processing options
|
|
82
141
|
* @returns A promise that resolves to the mapped array
|
|
83
142
|
* @throws {Error} When batchSize is not a positive integer
|
|
84
143
|
*
|
|
85
144
|
* @example
|
|
86
145
|
* ```typescript
|
|
87
|
-
* // Synchronous mapping
|
|
88
|
-
* const doubled = await mapInBatches([1, 2, 3, 4], (x) => x * 2
|
|
89
|
-
* // Result: [2, 4, 6, 8]
|
|
90
|
-
*
|
|
91
|
-
* // Asynchronous mapping
|
|
92
|
-
* const fetched = await mapInBatches(urls, async (url) => fetch(url), 3);
|
|
146
|
+
* // Synchronous mapping with default options (sequential processing)
|
|
147
|
+
* const doubled = await mapInBatches([1, 2, 3, 4], (x) => x * 2);
|
|
93
148
|
*
|
|
94
|
-
* // With
|
|
95
|
-
* const
|
|
96
|
-
* // Result: ['a-0', 'b-1']
|
|
149
|
+
* // With concurrent processing within batches
|
|
150
|
+
* const doubled = await mapInBatches([1, 2, 3, 4], (x) => x * 2, { sequentialProcessing: false });
|
|
97
151
|
* ```
|
|
98
152
|
*/
|
|
99
|
-
function mapInBatches(items, mapFn,
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
153
|
+
function mapInBatches(items, mapFn, options) {
|
|
154
|
+
const opts = getOptions(options);
|
|
155
|
+
return (async () => {
|
|
156
|
+
const result = [];
|
|
157
|
+
await processInBatches(items, opts, async (batch, batchStart) => {
|
|
158
|
+
if (opts.sequentialProcessing) {
|
|
159
|
+
// Process items sequentially
|
|
160
|
+
for (let j = 0; j < batch.length; j += 1) {
|
|
161
|
+
// eslint-disable-next-line no-await-in-loop -- sequential processing is required
|
|
162
|
+
const mapped = await mapFn(batch[j], batchStart + j);
|
|
163
|
+
result.push(mapped);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
// Process items concurrently
|
|
168
|
+
const mapped = await Promise.all(batch.map((item, j) => mapFn(item, batchStart + j)));
|
|
169
|
+
result.push(...mapped);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
return result;
|
|
173
|
+
})();
|
|
114
174
|
}
|
|
115
175
|
/**
|
|
116
176
|
* Filters an array in batches to avoid blocking the event loop.
|
|
@@ -120,44 +180,45 @@ function mapInBatches(items, mapFn, batchSize = defaultBatchSize, yieldThreshold
|
|
|
120
180
|
* @template T - The type of items in the array
|
|
121
181
|
* @param items - The array to filter
|
|
122
182
|
* @param predicate - The predicate function to test each item. Receives the item and its index.
|
|
123
|
-
* @param
|
|
124
|
-
* @param yieldThreshold - Time threshold in milliseconds before yielding control (default: @see defaultYieldThreshold)
|
|
183
|
+
* @param options - Batch processing options
|
|
125
184
|
* @returns A promise that resolves to the filtered array
|
|
126
185
|
* @throws {Error} When batchSize is not a positive integer
|
|
127
186
|
*
|
|
128
187
|
* @example
|
|
129
188
|
* ```typescript
|
|
130
|
-
* // Synchronous filtering
|
|
131
|
-
* const evens = await filterInBatches([1, 2, 3, 4, 5], (x) => x % 2 === 0
|
|
189
|
+
* // Synchronous filtering with default options
|
|
190
|
+
* const evens = await filterInBatches([1, 2, 3, 4, 5], (x) => x % 2 === 0);
|
|
132
191
|
* // Result: [2, 4]
|
|
133
192
|
*
|
|
134
|
-
* //
|
|
135
|
-
* const
|
|
136
|
-
* const response = await fetch(url);
|
|
137
|
-
* return response.ok;
|
|
138
|
-
* }, 3);
|
|
139
|
-
*
|
|
140
|
-
* // With index
|
|
141
|
-
* const evenIndices = await filterInBatches(['a', 'b', 'c'], (_, index) => index % 2 === 0);
|
|
142
|
-
* // Result: ['a', 'c']
|
|
193
|
+
* // With custom batch size
|
|
194
|
+
* const evens = await filterInBatches([1, 2, 3, 4, 5], (x) => x % 2 === 0, { batchSize: 2 });
|
|
143
195
|
* ```
|
|
144
196
|
*/
|
|
145
|
-
function filterInBatches(items, predicate,
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
197
|
+
function filterInBatches(items, predicate, options) {
|
|
198
|
+
const opts = getOptions(options);
|
|
199
|
+
return (async () => {
|
|
200
|
+
const result = [];
|
|
201
|
+
await processInBatches(items, opts, async (batch, batchStart) => {
|
|
202
|
+
if (opts.sequentialProcessing) {
|
|
203
|
+
// Process items sequentially
|
|
204
|
+
for (let j = 0; j < batch.length; j += 1) {
|
|
205
|
+
// eslint-disable-next-line no-await-in-loop -- sequential processing is required
|
|
206
|
+
const passes = await predicate(batch[j], batchStart + j);
|
|
207
|
+
if (passes)
|
|
208
|
+
result.push(batch[j]);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
// Process items concurrently
|
|
213
|
+
const flags = await Promise.all(batch.map((item, j) => predicate(item, batchStart + j)));
|
|
214
|
+
for (let j = 0; j < batch.length; j += 1) {
|
|
215
|
+
if (flags[j])
|
|
216
|
+
result.push(batch[j]);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
return result;
|
|
221
|
+
})();
|
|
161
222
|
}
|
|
162
223
|
/**
|
|
163
224
|
* Groups an array by a key function in batches to avoid blocking the event loop.
|
|
@@ -168,112 +229,94 @@ function filterInBatches(items, predicate, batchSize = defaultBatchSize, yieldTh
|
|
|
168
229
|
* @template K - The type of the grouping key (must extend PropertyKey)
|
|
169
230
|
* @param items - The array to group
|
|
170
231
|
* @param keyFn - The function to extract the grouping key from each item. Receives the item and its index.
|
|
171
|
-
* @param
|
|
172
|
-
* @param yieldThreshold - Time threshold in milliseconds before yielding control (default: @see defaultYieldThreshold)
|
|
232
|
+
* @param options - Batch processing options
|
|
173
233
|
* @returns A promise that resolves to an object with grouped items
|
|
174
234
|
* @throws {Error} When batchSize is not a positive integer
|
|
175
235
|
*
|
|
176
236
|
* @example
|
|
177
237
|
* ```typescript
|
|
178
|
-
* // Group by property
|
|
238
|
+
* // Group by property with default options
|
|
179
239
|
* const byType = await groupByInBatches(
|
|
180
240
|
* [{type: 'A', value: 1}, {type: 'B', value: 2}, {type: 'A', value: 3}],
|
|
181
|
-
* (item) => item.type
|
|
182
|
-
* 2
|
|
241
|
+
* (item) => item.type
|
|
183
242
|
* );
|
|
184
243
|
* // Result: {A: [{type: 'A', value: 1}, {type: 'A', value: 3}], B: [{type: 'B', value: 2}]}
|
|
185
244
|
*
|
|
186
|
-
* //
|
|
187
|
-
* const
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
* return await getCategoryForItem(item);
|
|
193
|
-
* });
|
|
245
|
+
* // With custom batch size
|
|
246
|
+
* const byType = await groupByInBatches(
|
|
247
|
+
* [{type: 'A', value: 1}, {type: 'B', value: 2}, {type: 'A', value: 3}],
|
|
248
|
+
* (item) => item.type,
|
|
249
|
+
* { batchSize: 2 }
|
|
250
|
+
* );
|
|
194
251
|
* ```
|
|
195
252
|
*/
|
|
196
|
-
function groupByInBatches(items, keyFn,
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
253
|
+
function groupByInBatches(items, keyFn, options) {
|
|
254
|
+
const opts = getOptions(options);
|
|
255
|
+
return (async () => {
|
|
256
|
+
const result = {};
|
|
257
|
+
await processInBatches(items, opts, async (batch, batchStart) => {
|
|
258
|
+
if (opts.sequentialProcessing) {
|
|
259
|
+
// Process items sequentially
|
|
260
|
+
for (let j = 0; j < batch.length; j += 1) {
|
|
261
|
+
// eslint-disable-next-line no-await-in-loop -- sequential processing is required
|
|
262
|
+
const key = await keyFn(batch[j], batchStart + j);
|
|
263
|
+
if (!result[key])
|
|
264
|
+
result[key] = [];
|
|
265
|
+
result[key].push(batch[j]);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
// Process items concurrently
|
|
270
|
+
const keys = await Promise.all(batch.map((item, j) => keyFn(item, batchStart + j)));
|
|
271
|
+
for (let j = 0; j < batch.length; j += 1) {
|
|
272
|
+
const key = keys[j];
|
|
273
|
+
if (!result[key])
|
|
274
|
+
result[key] = [];
|
|
275
|
+
result[key].push(batch[j]);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
return result;
|
|
280
|
+
})();
|
|
218
281
|
}
|
|
219
282
|
/**
|
|
220
283
|
* Reduces an array in batches to avoid blocking the event loop.
|
|
221
284
|
* Processes items in chunks and yields control back to the event loop between batches
|
|
222
|
-
* when the processing time exceeds the threshold.
|
|
285
|
+
* when the processing time exceeds the threshold. Sequential processing is always used for the reducer function,
|
|
286
|
+
* irrespective of the `sequentialProcessing` option.
|
|
223
287
|
*
|
|
224
288
|
* @template T - The type of items in the array
|
|
225
289
|
* @template R - The type of the accumulator/result
|
|
226
290
|
* @param items - The array to reduce
|
|
227
291
|
* @param reducer - The reducer function. Receives the accumulator, current item, and index.
|
|
228
292
|
* @param initialValue - The initial value for the accumulator
|
|
229
|
-
* @param
|
|
230
|
-
* @param yieldThreshold - Time threshold in milliseconds before yielding control (default: @see defaultYieldThreshold)
|
|
293
|
+
* @param options - Batch processing options
|
|
231
294
|
* @returns A promise that resolves to the reduced value
|
|
232
295
|
* @throws {Error} When batchSize is not a positive integer
|
|
233
296
|
*
|
|
234
297
|
* @example
|
|
235
298
|
* ```typescript
|
|
236
|
-
* // Sum numbers
|
|
237
|
-
* const sum = await reduceInBatches([1, 2, 3, 4], (acc, x) => acc + x, 0
|
|
299
|
+
* // Sum numbers with default options
|
|
300
|
+
* const sum = await reduceInBatches([1, 2, 3, 4], (acc, x) => acc + x, 0);
|
|
238
301
|
* // Result: 10
|
|
239
302
|
*
|
|
240
|
-
* //
|
|
241
|
-
* const
|
|
242
|
-
* // Result: 'abc'
|
|
243
|
-
*
|
|
244
|
-
* // Build object with index
|
|
245
|
-
* const indexed = await reduceInBatches(
|
|
246
|
-
* ['x', 'y'],
|
|
247
|
-
* (acc, item, index) => ({ ...acc, [index]: item }),
|
|
248
|
-
* {}
|
|
249
|
-
* );
|
|
250
|
-
* // Result: {0: 'x', 1: 'y'}
|
|
251
|
-
*
|
|
252
|
-
* // Asynchronous reducer
|
|
253
|
-
* const processed = await reduceInBatches(urls, async (acc, url) => {
|
|
254
|
-
* const data = await fetch(url).then(r => r.json());
|
|
255
|
-
* return [...acc, data];
|
|
256
|
-
* }, []);
|
|
303
|
+
* // With custom batch size
|
|
304
|
+
* const sum = await reduceInBatches([1, 2, 3, 4], (acc, x) => acc + x, 0, { batchSize: 2 });
|
|
257
305
|
* ```
|
|
258
306
|
*/
|
|
259
|
-
function reduceInBatches(items, reducer, initialValue,
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
return reducer(resolvedAcc, item, i + j);
|
|
273
|
-
}, Promise.resolve(acc));
|
|
274
|
-
return defer(startTime, yieldThreshold).then((didYield) => process(i + batchSize, reduced, didYield ? Date.now() : startTime));
|
|
275
|
-
};
|
|
276
|
-
return process();
|
|
307
|
+
function reduceInBatches(items, reducer, initialValue, options) {
|
|
308
|
+
const opts = getOptions(options);
|
|
309
|
+
return (async () => {
|
|
310
|
+
let acc = initialValue;
|
|
311
|
+
await processInBatches(items, opts, async (batch, batchStart) => {
|
|
312
|
+
// Always sequential, regardless of sequentialProcessing option
|
|
313
|
+
for (let j = 0; j < batch.length; j += 1) {
|
|
314
|
+
// eslint-disable-next-line no-await-in-loop -- sequential processing is required
|
|
315
|
+
acc = await reducer(acc, batch[j], batchStart + j);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
return acc;
|
|
319
|
+
})();
|
|
277
320
|
}
|
|
278
321
|
/**
|
|
279
322
|
* FlatMaps an array in batches to avoid blocking the event loop.
|
|
@@ -284,47 +327,83 @@ function reduceInBatches(items, reducer, initialValue, batchSize = defaultBatchS
|
|
|
284
327
|
* @template R - The type of items in the flattened result array
|
|
285
328
|
* @param items - The array to flatMap over
|
|
286
329
|
* @param mapFn - The mapping function that returns an array for each item. Receives the item and its index.
|
|
287
|
-
* @param
|
|
288
|
-
* @param yieldThreshold - Time threshold in milliseconds before yielding control (default: @see defaultYieldThreshold)
|
|
330
|
+
* @param options - Batch processing options
|
|
289
331
|
* @returns A promise that resolves to the flattened mapped array
|
|
290
332
|
* @throws {Error} When batchSize is not a positive integer
|
|
291
333
|
*
|
|
292
334
|
* @example
|
|
293
335
|
* ```typescript
|
|
294
|
-
* // Duplicate each item
|
|
295
|
-
* const duplicated = await flatMapInBatches([1, 2, 3], (x) => [x, x]
|
|
336
|
+
* // Duplicate each item with default options
|
|
337
|
+
* const duplicated = await flatMapInBatches([1, 2, 3], (x) => [x, x]);
|
|
296
338
|
* // Result: [1, 1, 2, 2, 3, 3]
|
|
297
339
|
*
|
|
298
|
-
* //
|
|
299
|
-
* const
|
|
300
|
-
*
|
|
340
|
+
* // With custom batch size
|
|
341
|
+
* const duplicated = await flatMapInBatches([1, 2, 3], (x) => [x, x], { batchSize: 2 });
|
|
342
|
+
* ```
|
|
343
|
+
*/
|
|
344
|
+
function flatMapInBatches(items, mapFn, options) {
|
|
345
|
+
const opts = getOptions(options);
|
|
346
|
+
return (async () => {
|
|
347
|
+
const result = [];
|
|
348
|
+
await processInBatches(items, opts, async (batch, batchStart) => {
|
|
349
|
+
if (opts.sequentialProcessing) {
|
|
350
|
+
// Process items sequentially
|
|
351
|
+
for (let j = 0; j < batch.length; j += 1) {
|
|
352
|
+
// eslint-disable-next-line no-await-in-loop -- sequential processing is required
|
|
353
|
+
const mapped = await mapFn(batch[j], batchStart + j);
|
|
354
|
+
result.push(...mapped);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
// Process items concurrently
|
|
359
|
+
const mapped = await Promise.all(batch.map((item, j) => mapFn(item, batchStart + j)));
|
|
360
|
+
mapped.forEach((arr) => {
|
|
361
|
+
result.push(...arr);
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
return result;
|
|
366
|
+
})();
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* forEach over an array in batches to avoid blocking the event loop.
|
|
370
|
+
* Processes items in chunks and yields control back to the event loop between batches
|
|
371
|
+
* when the processing time exceeds the threshold.
|
|
301
372
|
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
*
|
|
373
|
+
* @template T - The type of items in the input array
|
|
374
|
+
* @param items - The array to iterate over
|
|
375
|
+
* @param fn - The function to apply to each item. Receives the item and its index. Can be async.
|
|
376
|
+
* @param options - Batch processing options
|
|
377
|
+
* @returns A promise that resolves when all items have been processed
|
|
378
|
+
* @throws {Error} When batchSize is not a positive integer
|
|
305
379
|
*
|
|
306
|
-
*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
380
|
+
* @example
|
|
381
|
+
* ```typescript
|
|
382
|
+
* // Process items in batches with default options
|
|
383
|
+
* await forEachInBatches([1, 2, 3, 4], async (x) => {
|
|
384
|
+
* await doSomething(x);
|
|
310
385
|
* });
|
|
386
|
+
*
|
|
387
|
+
* // With custom batch size
|
|
388
|
+
* await forEachInBatches([1, 2, 3, 4], async (x) => {
|
|
389
|
+
* await doSomething(x);
|
|
390
|
+
* }, { batchSize: 2 });
|
|
311
391
|
* ```
|
|
312
392
|
*/
|
|
313
|
-
function
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
};
|
|
328
|
-
return process();
|
|
393
|
+
function forEachInBatches(items, fn, options) {
|
|
394
|
+
const opts = getOptions(options);
|
|
395
|
+
return processInBatches(items, opts, async (batch, batchStart) => {
|
|
396
|
+
if (opts.sequentialProcessing) {
|
|
397
|
+
// Process items sequentially
|
|
398
|
+
for (let j = 0; j < batch.length; j += 1) {
|
|
399
|
+
// eslint-disable-next-line no-await-in-loop -- sequential processing is required
|
|
400
|
+
await fn(batch[j], batchStart + j);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
// Process items concurrently
|
|
405
|
+
await Promise.all(batch.map((item, j) => fn(item, batchStart + j)));
|
|
406
|
+
}
|
|
407
|
+
});
|
|
329
408
|
}
|
|
330
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmF0Y2gtcHJvY2Vzc2luZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9iYXRjaC1wcm9jZXNzaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBcUNBLDRFQXVCQztBQXNERCxvQ0F3QkM7QUFnQ0QsMENBMEJDO0FBb0NELDRDQXNDQztBQTBDRCwwQ0E0QkM7QUFxQ0QsNENBeUJDO0FBbllELDBDQUEwQztBQUMxQyxJQUFJLGdCQUFnQixHQUFHLEVBQUUsQ0FBQztBQUMxQixJQUFJLHFCQUFxQixHQUFHLEVBQUUsQ0FBQztBQUUvQjs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFDSCxTQUFnQixnQ0FBZ0MsQ0FDOUMsTUFBZ0M7SUFFaEMsSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUNYLElBQUksTUFBTSxDQUFDLFNBQVMsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNuQyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLElBQUksTUFBTSxDQUFDLFNBQVMsSUFBSSxDQUFDLEVBQUUsQ0FBQztnQkFDakUsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFDO1lBQzFELENBQUM7WUFDRCxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDO1FBQ3RDLENBQUM7UUFFRCxJQUFJLE1BQU0sQ0FBQyxjQUFjLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDeEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxjQUFjLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQzFFLE1BQU0sSUFBSSxLQUFLLENBQUMsK0NBQStDLENBQUMsQ0FBQztZQUNuRSxDQUFDO1lBQ0QscUJBQXFCLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQztRQUNoRCxDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU87UUFDTCxTQUFTLEVBQUUsZ0JB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TyxFQUFFLENBQUM7QUFDbkIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciBiYXRjaCBwcm9jZXNzaW5nIG9wZXJhdGlvbnNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBCYXRjaFByb2Nlc3NpbmdEZWZhdWx0cyB7XG4gIC8qKlxuICAgKiBEZWZhdWx0IG51bWJlciBvZiBpdGVtcyB0byBwcm9jZXNzIGluIGVhY2ggYmF0Y2hcbiAgICovXG4gIGJhdGNoU2l6ZT86IG51bWJlcjtcblxuICAvKipcbiAgICogRGVmYXVsdCB0aW1lIHRocmVzaG9sZCBpbiBtaWxsaXNlY29uZHMgYmVmb3JlIHlpZWxkaW5nIGNvbnRyb2wgYmFjayB0byB0aGUgZXZlbnQgbG9vcFxuICAgKi9cbiAgeWllbGRUaHJlc2hvbGQ/OiBudW1iZXI7XG59XG5cbi8vIERlZmF1bHQgY29uZmlndXJhdGlvbiB2YWx1ZXMgKGludGVybmFsKVxubGV0IGRlZmF1bHRCYXRjaFNpemUgPSAxMDtcbmxldCBkZWZhdWx0WWllbGRUaHJlc2hvbGQgPSAxMDtcblxuLyoqXG4gKiBDb25maWd1cmUgZ2xvYmFsIGRlZmF1bHRzIGZvciBiYXRjaCBwcm9jZXNzaW5nIG9wZXJhdGlvbnNcbiAqXG4gKiBAcGFyYW0gY29uZmlnIC0gQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciBiYXRjaCBwcm9jZXNzaW5nXG4gKiBAcmV0dXJucyBUaGUgY3VycmVudCBjb25maWd1cmF0aW9uIGFmdGVyIGFwcGx5aW5nIGNoYW5nZXNcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gU2V0IGJvdGggZGVmYXVsdHNcbiAqIGNvbmZpZ3VyZUJhdGNoUHJvY2Vzc2luZ0RlZmF1bHRzKHsgYmF0Y2hTaXplOiAyMCwgeWllbGRUaHJlc2hvbGQ6IDUgfSk7XG4gKlxuICogLy8gU2V0IG9ubHkgYmF0Y2ggc2l6ZVxuICogY29uZmlndXJlQmF0Y2hQcm9jZXNzaW5nRGVmYXVsdHMoeyBiYXRjaFNpemU6IDUwIH0pO1xuICpcbiAqIC8vIEdldCBjdXJyZW50IGNvbmZpZ3VyYXRpb25cbiAqIGNvbnN0IGN1cnJlbnRDb25maWcgPSBjb25maWd1cmVCYXRjaFByb2Nlc3NpbmdEZWZhdWx0cygpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb25maWd1cmVCYXRjaFByb2Nlc3NpbmdEZWZhdWx0cyhcbiAgY29uZmlnPzogQmF0Y2hQcm9jZXNzaW5nRGVmYXVsdHMsXG4pOiBCYXRjaFByb2Nlc3NpbmdEZWZhdWx0cyB7XG4gIGlmIChjb25maWcpIHtcbiAgICBpZiAoY29uZmlnLmJhdGNoU2l6ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoY29uZmlnLmJhdGNoU2l6ZSkgfHwgY29uZmlnLmJhdGNoU2l6ZSA8PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignYmF0Y2hTaXplIG11c3QgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyJyk7XG4gICAgICB9XG4gICAgICBkZWZhdWx0QmF0Y2hTaXplID0gY29uZmlnLmJhdGNoU2l6ZTtcbiAgICB9XG5cbiAgICBpZiAoY29uZmlnLnlpZWxkVGhyZXNob2xkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihjb25maWcueWllbGRUaHJlc2hvbGQpIHx8IGNvbmZpZy55aWVsZFRocmVzaG9sZCA8IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd5aWVsZFRocmVzaG9sZCBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIGludGVnZXInKTtcbiAgICAgIH1cbiAgICAgIGRlZmF1bHRZaWVsZFRocmVzaG9sZCA9IGNvbmZpZy55aWVsZFRocmVzaG9sZDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGJhdGNoU2l6ZTogZGVmYXVsdEJhdGNoU2l6ZSxcbiAgICB5aWVsZFRocmVzaG9sZDogZGVmYXVsdFlpZWxkVGhyZXNob2xkLFxuICB9O1xufVxuXG4vKipcbiAqIFV0aWxpdHkgZnVuY3Rpb24gdG8gZGVmZXIgZXhlY3V0aW9uIHRvIHRoZSBuZXh0IHRpY2sgb2YgdGhlIGV2ZW50IGxvb3AuXG4gKiBUaGlzIHByZXZlbnRzIGJsb2NraW5nIHRoZSBldmVudCBsb29wIGR1cmluZyBoZWF2eSBiYXRjaCBvcGVyYXRpb25zIGJ5XG4gKiB5aWVsZGluZyBjb250cm9sIGJhY2sgdG8gdGhlIGV2ZW50IGxvb3AgdXNpbmcgc2V0SW1tZWRpYXRlLlxuICpcbiAqIEBwYXJhbSBzdGFydFRpbWUgLSBUaGUgdGltZXN0YW1wIHdoZW4gdGhlIGN1cnJlbnQgYmF0Y2ggcHJvY2Vzc2luZyBzdGFydGVkXG4gKiBAcGFyYW0geWllbGRUaHJlc2hvbGQgLSBUaW1lIHRocmVzaG9sZCBpbiBtaWxsaXNlY29uZHMgYmVmb3JlIHlpZWxkaW5nIGNvbnRyb2xcbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXIgYSB5aWVsZCBvY2N1cnJlZFxuICogQGludGVybmFsXG4gKi9cbmZ1bmN0aW9uIGRlZmVyKHN0YXJ0VGltZTogbnVtYmVyLCB5aWVsZFRocmVzaG9sZDogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIGNvbnN0IGVsYXBzZWQgPSBEYXRlLm5vdygpIC0gc3RhcnRUaW1lO1xuXG4gIC8vIE9ubHkgeWllbGQgaWYgd2UndmUgZXhjZWVkZWQgdGhlIHRocmVzaG9sZFxuICBpZiAoZWxhcHNlZCA+PSB5aWVsZFRocmVzaG9sZCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHJlc29sdmUodHJ1ZSkpO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gT3RoZXJ3aXNlIGNvbnRpbnVlIGltbWVkaWF0ZWx5XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoZmFsc2UpO1xufVxuXG4vKipcbiAqIE1hcHMgb3ZlciBhbiBhcnJheSBpbiBiYXRjaGVzIHRvIGF2b2lkIGJsb2NraW5nIHRoZSBldmVudCBsb29wLlxuICogUHJvY2Vzc2VzIGl0ZW1zIGluIGNodW5rcyBhbmQgeWllbGRzIGNvbnRyb2wgYmFjayB0byB0aGUgZXZlbnQgbG9vcCBiZXR3ZWVuIGJhdGNoZXNcbiAqIHdoZW4gdGhlIHByb2Nlc3NpbmcgdGltZSBleGNlZWRzIHRoZSB0aHJlc2hvbGQuXG4gKlxuICogQHRlbXBsYXRlIFQgLSBUaGUgdHlwZSBvZiBpdGVtcyBpbiB0aGUgaW5wdXQgYXJyYXlcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHR5cGUgb2YgaXRlbXMgaW4gdGhlIHJlc3VsdCBhcnJheVxuICogQHBhcmFtIGl0ZW1zIC0gVGhlIGFycmF5IHRvIG1hcCBvdmVyXG4gKiBAcGFyYW0gbWFwRm4gLSBUaGUgbWFwcGluZyBmdW5jdGlvbiB0byBhcHBseSB0byBlYWNoIGl0ZW0uIFJlY2VpdmVzIHRoZSBpdGVtIGFuZCBpdHMgaW5kZXguXG4gKiBAcGFyYW0gYmF0Y2hTaXplIC0gVGhlIG51bWJlciBvZiBpdGVtcyB0byBwcm9jZXNzIGluIGVhY2ggYmF0Y2ggKGRlZmF1bHQ6IEBzZWUgZGVmYXVsdEJhdGNoU2l6ZSlcbiAqIEBwYXJhbSB5aWVsZFRocmVzaG9sZCAtIFRpbWUgdGhyZXNob2xkIGluIG1pbGxpc2Vjb25kcyBiZWZvcmUgeWllbGRpbmcgY29udHJvbCAoZGVmYXVsdDogQHNlZSBkZWZhdWx0WWllbGRUaHJlc2hvbGQpXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgbWFwcGVkIGFycmF5XG4gKiBAdGhyb3dzIHtFcnJvcn0gV2hlbiBiYXRjaFNpemUgaXMgbm90IGEgcG9zaXRpdmUgaW50ZWdlclxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBTeW5jaHJvbm91cyBtYXBwaW5nXG4gKiBjb25zdCBkb3VibGVkID0gYXdhaXQgbWFwSW5CYXRjaGVzKFsxLCAyLCAzLCA0XSwgKHgpID0+IHggKiAyLCAyKTtcbiAqIC8vIFJlc3VsdDogWzIsIDQsIDYsIDhdXG4gKlxuICogLy8gQXN5bmNocm9ub3VzIG1hcHBpbmdcbiAqIGNvbnN0IGZldGNoZWQgPSBhd2FpdCBtYXBJbkJhdGNoZXModXJscywgYXN5bmMgKHVybCkgPT4gZmV0Y2godXJsKSwgMyk7XG4gKlxuICogLy8gV2l0aCBpbmRleFxuICogY29uc3QgaW5kZXhlZCA9IGF3YWl0IG1hcEluQmF0Y2hlcyhbJ2EnLCAnYiddLCAoaXRlbSwgaW5kZXgpID0+IGAke2l0ZW19LSR7aW5kZXh9YCk7XG4gKiAvLyBSZXN1bHQ6IFsnYS0wJywgJ2ItMSddXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1hcEluQmF0Y2hlczxULCBSPihcbiAgaXRlbXM6IFRbXSxcbiAgbWFwRm46IChpdGVtOiBULCBpbmRleDogbnVtYmVyKSA9PiBSIHwgUHJvbWlzZTxSPixcbiAgYmF0Y2hTaXplID0gZGVmYXVsdEJhdGNoU2l6ZSxcbiAgeWllbGRUaHJlc2hvbGQgPSBkZWZhdWx0WWllbGRUaHJlc2hvbGQsXG4pOiBQcm9taXNlPFJbXT4ge1xuICBpZiAoIU51bWJlci5pc0ludGVnZXIoYmF0Y2hTaXplKSB8fCBiYXRjaFNpemUgPD0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignYmF0Y2hTaXplIG11c3QgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyJyk7XG4gIH1cbiAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKHlpZWxkVGhyZXNob2xkKSB8fCB5aWVsZFRocmVzaG9sZCA8IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3lpZWxkVGhyZXNob2xkIG11c3QgYmUgYSBub24tbmVnYXRpdmUgaW50ZWdlcicpO1xuICB9XG4gIGNvbnN0IHByb2Nlc3MgPSBhc3luYyAoaSA9IDAsIGFjYzogUltdID0gW10sIHN0YXJ0VGltZSA9IERhdGUubm93KCkpOiBQcm9taXNlPFJbXT4gPT4ge1xuICAgIGlmIChpID49IGl0ZW1zLmxlbmd0aCkgcmV0dXJuIGFjYztcblxuICAgIGNvbnN0IGJhdGNoID0gaXRlbXMuc2xpY2UoaSwgaSArIGJhdGNoU2l6ZSk7XG4gICAgY29uc3QgbWFwcGVkID0gYXdhaXQgUHJvbWlzZS5hbGwoYmF0Y2gubWFwKChpdGVtLCBqKSA9PiBtYXBGbihpdGVtLCBpICsgaikpKTtcblxuICAgIHJldHVybiBkZWZlcihzdGFydFRpbWUsIHlpZWxkVGhyZXNob2xkKS50aGVuKChkaWRZaWVsZCkgPT5cbiAgICAgIHByb2Nlc3MoaSArIGJhdGNoU2l6ZSwgYWNjLmNvbmNhdChtYXBwZWQpLCBkaWRZaWVsZCA/IERhdGUubm93KCkgOiBzdGFydFRpbWUpLFxuICAgICk7XG4gIH07XG5cbiAgcmV0dXJuIHByb2Nlc3MoKTtcbn1cblxuLyoqXG4gKiBGaWx0ZXJzIGFuIGFycmF5IGluIGJhdGNoZXMgdG8gYXZvaWQgYmxvY2tpbmcgdGhlIGV2ZW50IGxvb3AuXG4gKiBQcm9jZXNzZXMgaXRlbXMgaW4gY2h1bmtzIGFuZCB5aWVsZHMgY29udHJvbCBiYWNrIHRvIHRoZSBldmVudCBsb29wIGJldHdlZW4gYmF0Y2hlc1xuICogd2hlbiB0aGUgcHJvY2Vzc2luZyB0aW1lIGV4Y2VlZHMgdGhlIHRocmVzaG9sZC5cbiAqXG4gKiBAdGVtcGxhdGUgVCAtIFRoZSB0eXBlIG9mIGl0ZW1zIGluIHRoZSBhcnJheVxuICogQHBhcmFtIGl0ZW1zIC0gVGhlIGFycmF5IHRvIGZpbHRlclxuICogQHBhcmFtIHByZWRpY2F0ZSAtIFRoZSBwcmVkaWNhdGUgZnVuY3Rpb24gdG8gdGVzdCBlYWNoIGl0ZW0uIFJlY2VpdmVzIHRoZSBpdGVtIGFuZCBpdHMgaW5kZXguXG4gKiBAcGFyYW0gYmF0Y2hTaXplIC0gVGhlIG51bWJlciBvZiBpdGVtcyB0byBwcm9jZXNzIGluIGVhY2ggYmF0Y2ggKGRlZmF1bHQ6IEBzZWUgZGVmYXVsdEJhdGNoU2l6ZSlcbiAqIEBwYXJhbSB5aWVsZFRocmVzaG9sZCAtIFRpbWUgdGhyZXNob2xkIGluIG1pbGxpc2Vjb25kcyBiZWZvcmUgeWllbGRpbmcgY29udHJvbCAoZGVmYXVsdDogQHNlZSBkZWZhdWx0WWllbGRUaHJlc2hvbGQpXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgZmlsdGVyZWQgYXJyYXlcbiAqIEB0aHJvd3Mge0Vycm9yfSBXaGVuIGJhdGNoU2l6ZSBpcyBub3QgYSBwb3NpdGl2ZSBpbnRlZ2VyXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIFN5bmNocm9ub3VzIGZpbHRlcmluZ1xuICogY29uc3QgZXZlbnMgPSBhd2FpdCBmaWx0ZXJJbkJhdGNoZXMoWzEsIDIsIDMsIDQsIDVdLCAoeCkgPT4geCAlIDIgPT09IDAsIDIpO1xuICogLy8gUmVzdWx0OiBbMiwgNF1cbiAqXG4gKiAvLyBBc3luY2hyb25vdXMgZmlsdGVyaW5nXG4gKiBjb25zdCB2YWxpZCA9IGF3YWl0IGZpbHRlckluQmF0Y2hlcyh1cmxzLCBhc3luYyAodXJsKSA9PiB7XG4gKiAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godXJsKTtcbiAqICAgcmV0dXJuIHJlc3BvbnNlLm9rO1xuICogfSwgMyk7XG4gKlxuICogLy8gV2l0aCBpbmRleFxuICogY29uc3QgZXZlbkluZGljZXMgPSBhd2FpdCBmaWx0ZXJJbkJhdGNoZXMoWydhJywgJ2InLCAnYyddLCAoXywgaW5kZXgpID0+IGluZGV4ICUgMiA9PT0gMCk7XG4gKiAvLyBSZXN1bHQ6IFsnYScsICdjJ11cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gZmlsdGVySW5CYXRjaGVzPFQ+KFxuICBpdGVtczogVFtdLFxuICBwcmVkaWNhdGU6IChpdGVtOiBULCBpbmRleDogbnVtYmVyKSA9PiBib29sZWFuIHwgUHJvbWlzZTxib29sZWFuPixcbiAgYmF0Y2hTaXplID0gZGVmYXVsdEJhdGNoU2l6ZSxcbiAgeWllbGRUaHJlc2hvbGQgPSBkZWZhdWx0WWllbGRUaHJlc2hvbGQsXG4pOiBQcm9taXNlPFRbXT4ge1xuICBpZiAoIU51bWJlci5pc0ludGVnZXIoYmF0Y2hTaXplKSB8fCBiYXRjaFNpemUgPD0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignYmF0Y2hTaXplIG11c3QgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyJyk7XG4gIH1cbiAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKHlpZWxkVGhyZXNob2xkKSB8fCB5aWVsZFRocmVzaG9sZCA8IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3lpZWxkVGhyZXNob2xkIG11c3QgYmUgYSBub24tbmVnYXRpdmUgaW50ZWdlcicpO1xuICB9XG4gIGNvbnN0IHByb2Nlc3MgPSBhc3luYyAoaSA9IDAsIGFjYzogVFtdID0gW10sIHN0YXJ0VGltZSA9IERhdGUubm93KCkpOiBQcm9taXNlPFRbXT4gPT4ge1xuICAgIGlmIChpID49IGl0ZW1zLmxlbmd0aCkgcmV0dXJuIGFjYztcblxuICAgIGNvbnN0IGJhdGNoID0gaXRlbXMuc2xpY2UoaSwgaSArIGJhdGNoU2l6ZSk7XG4gICAgY29uc3QgZmxhZ3MgPSBhd2FpdCBQcm9taXNlLmFsbChiYXRjaC5tYXAoKGl0ZW0sIGopID0+IHByZWRpY2F0ZShpdGVtLCBpICsgaikpKTtcblxuICAgIGNvbnN0IGZpbHRlcmVkID0gYmF0Y2guZmlsdGVyKChfLCBqKSA9PiBmbGFnc1tqXSk7XG5cbiAgICByZXR1cm4gZGVmZXIoc3RhcnRUaW1lLCB5aWVsZFRocmVzaG9sZCkudGhlbigoZGlkWWllbGQpID0+XG4gICAgICBwcm9jZXNzKGkgKyBiYXRjaFNpemUsIGFjYy5jb25jYXQoZmlsdGVyZWQpLCBkaWRZaWVsZCA/IERhdGUubm93KCkgOiBzdGFydFRpbWUpLFxuICAgICk7XG4gIH07XG5cbiAgcmV0dXJuIHByb2Nlc3MoKTtcbn1cblxuLyoqXG4gKiBHcm91cHMgYW4gYXJyYXkgYnkgYSBrZXkgZnVuY3Rpb24gaW4gYmF0Y2hlcyB0byBhdm9pZCBibG9ja2luZyB0aGUgZXZlbnQgbG9vcC5cbiAqIFByb2Nlc3NlcyBpdGVtcyBpbiBjaHVua3MgYW5kIHlpZWxkcyBjb250cm9sIGJhY2sgdG8gdGhlIGV2ZW50IGxvb3AgYmV0d2VlbiBiYXRjaGVzXG4gKiB3aGVuIHRoZSBwcm9jZXNzaW5nIHRpbWUgZXhjZWVkcyB0aGUgdGhyZXNob2xkLlxuICpcbiAqIEB0ZW1wbGF0ZSBUIC0gVGhlIHR5cGUgb2YgaXRlbXMgaW4gdGhlIGFycmF5XG4gKiBAdGVtcGxhdGUgSyAtIFRoZSB0eXBlIG9mIHRoZSBncm91cGluZyBrZXkgKG11c3QgZXh0ZW5kIFByb3BlcnR5S2V5KVxuICogQHBhcmFtIGl0ZW1zIC0gVGhlIGFycmF5IHRvIGdyb3VwXG4gKiBAcGFyYW0ga2V5Rm4gLSBUaGUgZnVuY3Rpb24gdG8gZXh0cmFjdCB0aGUgZ3JvdXBpbmcga2V5IGZyb20gZWFjaCBpdGVtLiBSZWNlaXZlcyB0aGUgaXRlbSBhbmQgaXRzIGluZGV4LlxuICogQHBhcmFtIGJhdGNoU2l6ZSAtIFRoZSBudW1iZXIgb2YgaXRlbXMgdG8gcHJvY2VzcyBpbiBlYWNoIGJhdGNoIChkZWZhdWx0OiBAc2VlIGRlZmF1bHRCYXRjaFNpemUpXG4gKiBAcGFyYW0geWllbGRUaHJlc2hvbGQgLSBUaW1lIHRocmVzaG9sZCBpbiBtaWxsaXNlY29uZHMgYmVmb3JlIHlpZWxkaW5nIGNvbnRyb2wgKGRlZmF1bHQ6IEBzZWUgZGVmYXVsdFlpZWxkVGhyZXNob2xkKVxuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IHdpdGggZ3JvdXBlZCBpdGVtc1xuICogQHRocm93cyB7RXJyb3J9IFdoZW4gYmF0Y2hTaXplIGlzIG5vdCBhIHBvc2l0aXZlIGludGVnZXJcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gR3JvdXAgYnkgcHJvcGVydHlcbiAqIGNvbnN0IGJ5VHlwZSA9IGF3YWl0IGdyb3VwQnlJbkJhdGNoZXMoXG4gKiAgIFt7dHlwZTogJ0EnLCB2YWx1ZTogMX0sIHt0eXBlOiAnQicsIHZhbHVlOiAyfSwge3R5cGU6ICdBJywgdmFsdWU6IDN9XSxcbiAqICAgKGl0ZW0pID0+IGl0ZW0udHlwZSxcbiAqICAgMlxuICogKTtcbiAqIC8vIFJlc3VsdDoge0E6IFt7dHlwZTogJ0EnLCB2YWx1ZTogMX0sIHt0eXBlOiAnQScsIHZhbHVlOiAzfV0sIEI6IFt7dHlwZTogJ0InLCB2YWx1ZTogMn1dfVxuICpcbiAqIC8vIEdyb3VwIGJ5IGNvbXB1dGVkIHZhbHVlXG4gKiBjb25zdCBieVBhcml0eSA9IGF3YWl0IGdyb3VwQnlJbkJhdGNoZXMoWzEsIDIsIDMsIDRdLCAoeCkgPT4geCAlIDIgPT09IDAgPyAnZXZlbicgOiAnb2RkJyk7XG4gKiAvLyBSZXN1bHQ6IHtvZGQ6IFsxLCAzXSwgZXZlbjogWzIsIDRdfVxuICpcbiAqIC8vIEFzeW5jaHJvbm91cyBrZXkgZnVuY3Rpb25cbiAqIGNvbnN0IGJ5Q2F0ZWdvcnkgPSBhd2FpdCBncm91cEJ5SW5CYXRjaGVzKGl0ZW1zLCBhc3luYyAoaXRlbSkgPT4ge1xuICogICByZXR1cm4gYXdhaXQgZ2V0Q2F0ZWdvcnlGb3JJdGVtKGl0ZW0pO1xuICogfSk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdyb3VwQnlJbkJhdGNoZXM8VCwgSyBleHRlbmRzIFByb3BlcnR5S2V5PihcbiAgaXRlbXM6IFRbXSxcbiAga2V5Rm46IChpdGVtOiBULCBpbmRleDogbnVtYmVyKSA9PiBLIHwgUHJvbWlzZTxLPixcbiAgYmF0Y2hTaXplID0gZGVmYXVsdEJhdGNoU2l6ZSxcbiAgeWllbGRUaHJlc2hvbGQgPSBkZWZhdWx0WWllbGRUaHJlc2hvbGQsXG4pOiBQcm9taXNlPFJlY29yZDxLLCBUW10+PiB7XG4gIGlmICghTnVtYmVyLmlzSW50ZWdlcihiYXRjaFNpemUpIHx8IGJhdGNoU2l6ZSA8PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdiYXRjaFNpemUgbXVzdCBiZSBhIHBvc2l0aXZlIGludGVnZXInKTtcbiAgfVxuICBpZiAoIU51bWJlci5pc0ludGVnZXIoeWllbGRUaHJlc2hvbGQpIHx8IHlpZWxkVGhyZXNob2xkIDwgMCkge1xuICAgIHRocm93IG5ldyBFcnJvcigneWllbGRUaHJlc2hvbGQgbXVzdCBiZSBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyJyk7XG4gIH1cbiAgY29uc3QgcHJvY2VzcyA9IGFzeW5jIChcbiAgICBpID0gMCxcbiAgICBhY2M6IFJlY29yZDxLLCBUW10+ID0ge30gYXMgUmVjb3JkPEssIFRbXT4sXG4gICAgc3RhcnRUaW1lID0gRGF0ZS5ub3coKSxcbiAgKTogUHJvbWlzZTxSZWNvcmQ8SywgVFtdPj4gPT4ge1xuICAgIGlmIChpID49IGl0ZW1zLmxlbmd0aCkgcmV0dXJuIGFjYztcblxuICAgIGNvbnN0IGJhdGNoID0gaXRlbXMuc2xpY2UoaSwgaSArIGJhdGNoU2l6ZSk7XG4gICAgY29uc3Qga2V5cyA9IGF3YWl0IFByb21pc2UuYWxsKGJhdGNoLm1hcCgoaXRlbSwgaikgPT4ga2V5Rm4oaXRlbSwgaSArIGopKSk7XG5cbiAgICBjb25zdCB1cGRhdGVkID0ga2V5cy5yZWR1Y2UoXG4gICAgICAocmVzLCBrZXksIGopID0+IHtcbiAgICAgICAgY29uc3QgaXRlbSA9IGJhdGNoW2pdO1xuICAgICAgICBpZiAoIXJlc1trZXldKSByZXNba2V5XSA9IFtdO1xuICAgICAgICByZXNba2V5XSA9IHJlc1trZXldLmNvbmNhdChpdGVtKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgIH0sXG4gICAgICB7IC4uLmFjYyB9LFxuICAgICk7XG5cbiAgICByZXR1cm4gZGVmZXIoc3RhcnRUaW1lLCB5aWVsZFRocmVzaG9sZCkudGhlbigoZGlkWWllbGQpID0+XG4gICAgICBwcm9jZXNzKGkgKyBiYXRjaFNpemUsIHVwZGF0ZWQsIGRpZFlpZWxkID8gRGF0ZS5ub3coKSA6IHN0YXJ0VGltZSksXG4gICAgKTtcbiAgfTtcblxuICByZXR1cm4gcHJvY2VzcygpO1xufVxuXG4vKipcbiAqIFJlZHVjZXMgYW4gYXJyYXkgaW4gYmF0Y2hlcyB0byBhdm9pZCBibG9ja2luZyB0aGUgZXZlbnQgbG9vcC5cbiAqIFByb2Nlc3NlcyBpdGVtcyBpbiBjaHVua3MgYW5kIHlpZWxkcyBjb250cm9sIGJhY2sgdG8gdGhlIGV2ZW50IGxvb3AgYmV0d2VlbiBiYXRjaGVzXG4gKiB3aGVuIHRoZSBwcm9jZXNzaW5nIHRpbWUgZXhjZWVkcyB0aGUgdGhyZXNob2xkLlxuICpcbiAqIEB0ZW1wbGF0ZSBUIC0gVGhlIHR5cGUgb2YgaXRlbXMgaW4gdGhlIGFycmF5XG4gKiBAdGVtcGxhdGUgUiAtIFRoZSB0eXBlIG9mIHRoZSBhY2N1bXVsYXRvci9yZXN1bHRcbiAqIEBwYXJhbSBpdGVtcyAtIFRoZSBhcnJheSB0byByZWR1Y2VcbiAqIEBwYXJhbSByZWR1Y2VyIC0gVGhlIHJlZHVjZXIgZnVuY3Rpb24uIFJlY2VpdmVzIHRoZSBhY2N1bXVsYXRvciwgY3VycmVudCBpdGVtLCBhbmQgaW5kZXguXG4gKiBAcGFyYW0gaW5pdGlhbFZhbHVlIC0gVGhlIGluaXRpYWwgdmFsdWUgZm9yIHRoZSBhY2N1bXVsYXRvclxuICogQHBhcmFtIGJhdGNoU2l6ZSAtIFRoZSBudW1iZXIgb2YgaXRlbXMgdG8gcHJvY2VzcyBpbiBlYWNoIGJhdGNoIChkZWZhdWx0OiBAc2VlIGRlZmF1bHRCYXRjaFNpemUpXG4gKiBAcGFyYW0geWllbGRUaHJlc2hvbGQgLSBUaW1lIHRocmVzaG9sZCBpbiBtaWxsaXNlY29uZHMgYmVmb3JlIHlpZWxkaW5nIGNvbnRyb2wgKGRlZmF1bHQ6IEBzZWUgZGVmYXVsdFlpZWxkVGhyZXNob2xkKVxuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHJlZHVjZWQgdmFsdWVcbiAqIEB0aHJvd3Mge0Vycm9yfSBXaGVuIGJhdGNoU2l6ZSBpcyBub3QgYSBwb3NpdGl2ZSBpbnRlZ2VyXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIFN1bSBudW1iZXJzXG4gKiBjb25zdCBzdW0gPSBhd2FpdCByZWR1Y2VJbkJhdGNoZXMoWzEsIDIsIDMsIDRdLCAoYWNjLCB4KSA9PiBhY2MgKyB4LCAwLCAyKTtcbiAqIC8vIFJlc3VsdDogMTBcbiAqXG4gKiAvLyBDb25jYXRlbmF0ZSBzdHJpbmdzXG4gKiBjb25zdCBqb2luZWQgPSBhd2FpdCByZWR1Y2VJbkJhdGNoZXMoWydhJywgJ2InLCAnYyddLCAoYWNjLCB4KSA9PiBhY2MgKyB4LCAnJyk7XG4gKiAvLyBSZXN1bHQ6ICdhYmMnXG4gKlxuICogLy8gQnVpbGQgb2JqZWN0IHdpdGggaW5kZXhcbiAqIGNvbnN0IGluZGV4ZWQgPSBhd2FpdCByZWR1Y2VJbkJhdGNoZXMoXG4gKiAgIFsneCcsICd5J10sXG4gKiAgIChhY2MsIGl0ZW0sIGluZGV4KSA9PiAoeyAuLi5hY2MsIFtpbmRleF06IGl0ZW0gfSksXG4gKiAgIHt9XG4gKiApO1xuICogLy8gUmVzdWx0OiB7MDogJ3gnLCAxOiAneSd9XG4gKlxuICogLy8gQXN5bmNocm9ub3VzIHJlZHVjZXJcbiAqIGNvbnN0IHByb2Nlc3NlZCA9IGF3YWl0IHJlZHVjZUluQmF0Y2hlcyh1cmxzLCBhc3luYyAoYWNjLCB1cmwpID0+IHtcbiAqICAgY29uc3QgZGF0YSA9IGF3YWl0IGZldGNoKHVybCkudGhlbihyID0+IHIuanNvbigpKTtcbiAqICAgcmV0dXJuIFsuLi5hY2MsIGRhdGFdO1xuICogfSwgW10pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWR1Y2VJbkJhdGNoZXM8VCwgUj4oXG4gIGl0ZW1zOiBUW10sXG4gIHJlZHVjZXI6IChhY2M6IFIsIGl0ZW06IFQsIGluZGV4OiBudW1iZXIpID0+IFIgfCBQcm9taXNlPFI+LFxuICBpbml0aWFsVmFsdWU6IFIsXG4gIGJhdGNoU2l6ZSA9IGRlZmF1bHRCYXRjaFNpemUsXG4gIHlpZWxkVGhyZXNob2xkID0gZGVmYXVsdFlpZWxkVGhyZXNob2xkLFxuKTogUHJvbWlzZTxSPiB7XG4gIGlmICghTnVtYmVyLmlzSW50ZWdlcihiYXRjaFNpemUpIHx8IGJhdGNoU2l6ZSA8PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdiYXRjaFNpemUgbXVzdCBiZSBhIHBvc2l0aXZlIGludGVnZXInKTtcbiAgfVxuICBpZiAoIU51bWJlci5pc0ludGVnZXIoeWllbGRUaHJlc2hvbGQpIHx8IHlpZWxkVGhyZXNob2xkIDwgMCkge1xuICAgIHRocm93IG5ldyBFcnJvcigneWllbGRUaHJlc2hvbGQgbXVzdCBiZSBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyJyk7XG4gIH1cbiAgY29uc3QgcHJvY2VzcyA9IGFzeW5jIChpID0gMCwgYWNjOiBSID0gaW5pdGlhbFZhbHVlLCBzdGFydFRpbWUgPSBEYXRlLm5vdygpKTogUHJvbWlzZTxSPiA9PiB7XG4gICAgaWYgKGkgPj0gaXRlbXMubGVuZ3RoKSByZXR1cm4gYWNjO1xuXG4gICAgY29uc3QgYmF0Y2ggPSBpdGVtcy5zbGljZShpLCBpICsgYmF0Y2hTaXplKTtcbiAgICBjb25zdCByZWR1Y2VkID0gYXdhaXQgYmF0Y2gucmVkdWNlPFByb21pc2U8Uj4+KGFzeW5jIChwcmV2QWNjLCBpdGVtLCBqKSA9PiB7XG4gICAgICBjb25zdCByZXNvbHZlZEFjYyA9IGF3YWl0IHByZXZBY2M7XG4gICAgICByZXR1cm4gcmVkdWNlcihyZXNvbHZlZEFjYywgaXRlbSwgaSArIGopO1xuICAgIH0sIFByb21pc2UucmVzb2x2ZShhY2MpKTtcblxuICAgIHJldHVybiBkZWZlcihzdGFydFRpbWUsIHlpZWxkVGhyZXNob2xkKS50aGVuKChkaWRZaWVsZCkgPT5cbiAgICAgIHByb2Nlc3MoaSArIGJhdGNoU2l6ZSwgcmVkdWNlZCwgZGlkWWllbGQgPyBEYXRlLm5vdygpIDogc3RhcnRUaW1lKSxcbiAgICApO1xuICB9O1xuXG4gIHJldHVybiBwcm9jZXNzKCk7XG59XG5cbi8qKlxuICogRmxhdE1hcHMgYW4gYXJyYXkgaW4gYmF0Y2hlcyB0byBhdm9pZCBibG9ja2luZyB0aGUgZXZlbnQgbG9vcC5cbiAqIFByb2Nlc3NlcyBpdGVtcyBpbiBjaHVua3MsIGZsYXR0ZW5zIHRoZSByZXN1bHRzLCBhbmQgeWllbGRzIGNvbnRyb2wgYmFjayB0byB0aGUgZXZlbnQgbG9vcCBiZXR3ZWVuIGJhdGNoZXNcbiAqIHdoZW4gdGhlIHByb2Nlc3NpbmcgdGltZSBleGNlZWRzIHRoZSB0aHJlc2hvbGQuXG4gKlxuICogQHRlbXBsYXRlIFQgLSBUaGUgdHlwZSBvZiBpdGVtcyBpbiB0aGUgaW5wdXQgYXJyYXlcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHR5cGUgb2YgaXRlbXMgaW4gdGhlIGZsYXR0ZW5lZCByZXN1bHQgYXJyYXlcbiAqIEBwYXJhbSBpdGVtcyAtIFRoZSBhcnJheSB0byBmbGF0TWFwIG92ZXJcbiAqIEBwYXJhbSBtYXBGbiAtIFRoZSBtYXBwaW5nIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhbiBhcnJheSBmb3IgZWFjaCBpdGVtLiBSZWNlaXZlcyB0aGUgaXRlbSBhbmQgaXRzIGluZGV4LlxuICogQHBhcmFtIGJhdGNoU2l6ZSAtIFRoZSBudW1iZXIgb2YgaXRlbXMgdG8gcHJvY2VzcyBpbiBlYWNoIGJhdGNoIChkZWZhdWx0OiBAc2VlIGRlZmF1bHRCYXRjaFNpemUpXG4gKiBAcGFyYW0geWllbGRUaHJlc2hvbGQgLSBUaW1lIHRocmVzaG9sZCBpbiBtaWxsaXNlY29uZHMgYmVmb3JlIHlpZWxkaW5nIGNvbnRyb2wgKGRlZmF1bHQ6IEBzZWUgZGVmYXVsdFlpZWxkVGhyZXNob2xkKVxuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGZsYXR0ZW5lZCBtYXBwZWQgYXJyYXlcbiAqIEB0aHJvd3Mge0Vycm9yfSBXaGVuIGJhdGNoU2l6ZSBpcyBub3QgYSBwb3NpdGl2ZSBpbnRlZ2VyXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIER1cGxpY2F0ZSBlYWNoIGl0ZW1cbiAqIGNvbnN0IGR1cGxpY2F0ZWQgPSBhd2FpdCBmbGF0TWFwSW5CYXRjaGVzKFsxLCAyLCAzXSwgKHgpID0+IFt4LCB4XSwgMik7XG4gKiAvLyBSZXN1bHQ6IFsxLCAxLCAyLCAyLCAzLCAzXVxuICpcbiAqIC8vIFZhcmlhYmxlIGxlbmd0aCByZXN1bHRzXG4gKiBjb25zdCByZXBlYXRlZCA9IGF3YWl0IGZsYXRNYXBJbkJhdGNoZXMoWzEsIDIsIDNdLCAoeCkgPT4gQXJyYXkoeCkuZmlsbCh4KSk7XG4gKiAvLyBSZXN1bHQ6IFsxLCAyLCAyLCAzLCAzLCAzXVxuICpcbiAqIC8vIFNwbGl0IHN0cmluZ3MgaW50byBjaGFyYWN0ZXJzXG4gKiBjb25zdCBjaGFycyA9IGF3YWl0IGZsYXRNYXBJbkJhdGNoZXMoWydhYicsICdjZCddLCAoc3RyKSA9PiBzdHIuc3BsaXQoJycpKTtcbiAqIC8vIFJlc3VsdDogWydhJywgJ2InLCAnYycsICdkJ11cbiAqXG4gKiAvLyBBc3luY2hyb25vdXMgbWFwcGluZ1xuICogY29uc3QgZXhwYW5kZWQgPSBhd2FpdCBmbGF0TWFwSW5CYXRjaGVzKGNhdGVnb3JpZXMsIGFzeW5jIChjYXRlZ29yeSkgPT4ge1xuICogICBjb25zdCBpdGVtcyA9IGF3YWl0IGZldGNoSXRlbXNGb3JDYXRlZ29yeShjYXRlZ29yeSk7XG4gKiAgIHJldHVybiBpdGVtcztcbiAqIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbGF0TWFwSW5CYXRjaGVzPFQsIFI+KFxuICBpdGVtczogVFtdLFxuICBtYXBGbjogKGl0ZW06IFQsIGluZGV4OiBudW1iZXIpID0+IFJbXSB8IFByb21pc2U8UltdPixcbiAgYmF0Y2hTaXplID0gZGVmYXVsdEJhdGNoU2l6ZSxcbiAgeWllbGRUaHJlc2hvbGQgPSBkZWZhdWx0WWllbGRUaHJlc2hvbGQsXG4pOiBQcm9taXNlPFJbXT4ge1xuICBpZiAoIU51bWJlci5pc0ludGVnZXIoYmF0Y2hTaXplKSB8fCBiYXRjaFNpemUgPD0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignYmF0Y2hTaXplIG11c3QgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyJyk7XG4gIH1cbiAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKHlpZWxkVGhyZXNob2xkKSB8fCB5aWVsZFRocmVzaG9sZCA8IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3lpZWxkVGhyZXNob2xkIG11c3QgYmUgYSBub24tbmVnYXRpdmUgaW50ZWdlcicpO1xuICB9XG4gIGNvbnN0IHByb2Nlc3MgPSBhc3luYyAoaSA9IDAsIGFjYzogUltdID0gW10sIHN0YXJ0VGltZSA9IERhdGUubm93KCkpOiBQcm9taXNlPFJbXT4gPT4ge1xuICAgIGlmIChpID49IGl0ZW1zLmxlbmd0aCkgcmV0dXJuIGFjYztcblxuICAgIGNvbnN0IGJhdGNoID0gaXRlbXMuc2xpY2UoaSwgaSArIGJhdGNoU2l6ZSk7XG4gICAgY29uc3QgbWFwcGVkID0gYXdhaXQgUHJvbWlzZS5hbGwoYmF0Y2gubWFwKChpdGVtLCBqKSA9PiBtYXBGbihpdGVtLCBpICsgaikpKTtcbiAgICBjb25zdCBmbGF0dGVuZWQgPSBtYXBwZWQucmVkdWNlKChhbGwsIGFycikgPT4gYWxsLmNvbmNhdChhcnIpLCBbXSk7XG5cbiAgICByZXR1cm4gZGVmZXIoc3RhcnRUaW1lLCB5aWVsZFRocmVzaG9sZCkudGhlbigoZGlkWWllbGQpID0+XG4gICAgICBwcm9jZXNzKGkgKyBiYXRjaFNpemUsIGFjYy5jb25jYXQoZmxhdHRlbmVkKSwgZGlkWWllbGQgPyBEYXRlLm5vdygpIDogc3RhcnRUaW1lKSxcbiAgICApO1xuICB9O1xuXG4gIHJldHVybiBwcm9jZXNzKCk7XG59XG4iXX0=
|
|
409
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmF0Y2gtcHJvY2Vzc2luZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9iYXRjaC1wcm9jZXNzaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBa0RBLDRFQTRCQztBQTBHRCxvQ0F5QkM7QUF3QkQsMENBMkJDO0FBZ0NELDRDQThCQztBQTJCRCwwQ0FtQkM7QUF5QkQsNENBMkJDO0FBMkJELDRDQW1CQztBQTFiRCwwQ0FBMEM7QUFDMUMsSUFBSSxnQkFBZ0IsR0FBRyxFQUFFLENBQUM7QUFDMUIsSUFBSSxxQkFBcUIsR0FBRyxFQUFFLENBQUM7QUFDL0IsSUFBSSwyQkFBMkIsR0FBRyxJQUFJLENBQUM7QUFFdkM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBQ0gsU0FBZ0IsZ0NBQWdDLENBQzlDLE1BQStCO0lBRS9CLElBQUksTUFBTSxFQUFFLENBQUM7UUFDWCxJQUFJLE1BQU0sQ0FBQyxTQUFTLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDbkMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxTQUFTLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQ2pFLE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLENBQUMsQ0FBQztZQUMxRCxDQUFDO1lBQ0QsZ0JBQWdCLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQztRQUN0QyxDQUFDO1FBRUQsSUFBSSxNQUFNLENBQUMsY0FBYyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3hDLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxNQUFNLENBQUMsY0FBYyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUMxRSxNQUFNLElBQUksS0FBSyxDQUFDLCtDQUErQyxDQUFDLENBQUM7WUFDbkUsQ0FBQztZQUNELHFCQUFxQixHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUM7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Tiw2QkFBNkI7WUFDN0IsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLFVBQVUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdEUsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogT3B0aW9ucyBmb3IgYmF0Y2ggcHJvY2Vzc2luZyBvcGVyYXRpb25zXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQmF0Y2hQcm9jZXNzaW5nT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBOdW1iZXIgb2YgaXRlbXMgdG8gcHJvY2VzcyBpbiBlYWNoIGJhdGNoIChkZWZhdWx0OiAxMClcbiAgICogTXVzdCBiZSBhIHBvc2l0aXZlIGludGVnZXIuXG4gICAqL1xuICBiYXRjaFNpemU/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRpbWUgdGhyZXNob2xkIGluIG1pbGxpc2Vjb25kcyAoZGVmYXVsdDogMTApIGJlZm9yZSB5aWVsZGluZyBjb250cm9sIGJhY2sgdG8gdGhlIGV2ZW50IGxvb3AuXG4gICAqIFNldCB0byAwIHRvIHlpZWxkIGFmdGVyIGV2ZXJ5IGJhdGNoLiBNdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIGludGVnZXIuXG4gICAqL1xuICB5aWVsZFRocmVzaG9sZD86IG51bWJlcjtcblxuICAvKipcbiAgICogV2hldGhlciB0byBwcm9jZXNzIGl0ZW1zIHNlcXVlbnRpYWxseSB3aXRoaW4gZWFjaCBiYXRjaC4gV2hlbiB0cnVlIChkZWZhdWx0KSwgZWFjaCBpdGVtIGluIGEgYmF0Y2hcbiAgICogd2lsbCBiZSBwcm9jZXNzZWQgb25lIGF0IGEgdGltZS4gV2hlbiBmYWxzZSwgYWxsIGl0ZW1zIGluIGEgYmF0Y2ggd2lsbCBiZSBwcm9jZXNzZWQgY29uY3VycmVudGx5LlxuICAgKiBDb25zaWRlciB0aGUgaW1wbGljYXRpb25zIG9mIGNvbmN1cnJlbmN5IG9uIHlvdXIgcHJvY2Vzc2luZyBsb2dpYyBiZWZvcmUgc2V0dGluZyB0aGlzIHRvIGZhbHNlLCBlLmcuIHJhY2UgY29uZGl0aW9ucywgcmF0ZSBsaW1pdHMsIG1lbW9yeSBwcmVzc3VyZSwgZXRjLlxuICAgKi9cbiAgc2VxdWVudGlhbFByb2Nlc3Npbmc/OiBib29sZWFuO1xufVxuXG4vLyBEZWZhdWx0IGNvbmZpZ3VyYXRpb24gdmFsdWVzIChpbnRlcm5hbClcbmxldCBkZWZhdWx0QmF0Y2hTaXplID0gMTA7XG5sZXQgZGVmYXVsdFlpZWxkVGhyZXNob2xkID0gMTA7XG5sZXQgZGVmYXVsdFNlcXVlbnRpYWxQcm9jZXNzaW5nID0gdHJ1ZTtcblxuLyoqXG4gKiBDb25maWd1cmUgZ2xvYmFsIGRlZmF1bHRzIGZvciBiYXRjaCBwcm9jZXNzaW5nIG9wZXJhdGlvbnNcbiAqXG4gKiBAcGFyYW0gY29uZmlnIC0gQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciBiYXRjaCBwcm9jZXNzaW5nXG4gKiBAcmV0dXJucyBUaGUgY3VycmVudCBjb25maWd1cmF0aW9uIGFmdGVyIGFwcGx5aW5nIGNoYW5nZXNcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gU2V0IGJvdGggZGVmYXVsdHNcbiAqIGNvbmZpZ3VyZUJhdGNoUHJvY2Vzc2luZ0RlZmF1bHRzKHsgYmF0Y2hTaXplOiAyMCwgeWllbGRUaHJlc2hvbGQ6IDUgfSk7XG4gKlxuICogLy8gU2V0IG9ubHkgYmF0Y2ggc2l6ZVxuICogY29uZmlndXJlQmF0Y2hQcm9jZXNzaW5nRGVmYXVsdHMoeyBiYXRjaFNpemU6IDUwIH0pO1xuICpcbiAqIC8vIEVuYWJsZSBjb25jdXJyZW50IHByb2Nlc3Npbmcgd2l0aGluIGJhdGNoZXNcbiAqIGNvbmZpZ3VyZUJhdGNoUHJvY2Vzc2luZ0RlZmF1bHRzKHsgc2VxdWVudGlhbFByb2Nlc3Npbmc6IGZhbHNlIH0pO1xuICpcbiAqIC8vIEdldCBjdXJyZW50IGNvbmZpZ3VyYXRpb25cbiAqIGNvbnN0IGN1cnJlbnRDb25maWcgPSBjb25maWd1cmVCYXRjaFByb2Nlc3NpbmdEZWZhdWx0cygpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb25maWd1cmVCYXRjaFByb2Nlc3NpbmdEZWZhdWx0cyhcbiAgY29uZmlnPzogQmF0Y2hQcm9jZXNzaW5nT3B0aW9ucyxcbik6IEJhdGNoUHJvY2Vzc2luZ09wdGlvbnMge1xuICBpZiAoY29uZmlnKSB7XG4gICAgaWYgKGNvbmZpZy5iYXRjaFNpemUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGNvbmZpZy5iYXRjaFNpemUpIHx8IGNvbmZpZy5iYXRjaFNpemUgPD0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2JhdGNoU2l6ZSBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlcicpO1xuICAgICAgfVxuICAgICAgZGVmYXVsdEJhdGNoU2l6ZSA9IGNvbmZpZy5iYXRjaFNpemU7XG4gICAgfVxuXG4gICAgaWYgKGNvbmZpZy55aWVsZFRocmVzaG9sZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoY29uZmlnLnlpZWxkVGhyZXNob2xkKSB8fCBjb25maWcueWllbGRUaHJlc2hvbGQgPCAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigneWllbGRUaHJlc2hvbGQgbXVzdCBiZSBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyJyk7XG4gICAgICB9XG4gICAgICBkZWZhdWx0WWllbGRUaHJlc2hvbGQgPSBjb25maWcueWllbGRUaHJlc2hvbGQ7XG4gICAgfVxuXG4gICAgaWYgKGNvbmZpZy5zZXF1ZW50aWFsUHJvY2Vzc2luZyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBkZWZhdWx0U2VxdWVudGlhbFByb2Nlc3NpbmcgPSBCb29sZWFuKGNvbmZpZy5zZXF1ZW50aWFsUHJvY2Vzc2luZyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBiYXRjaFNpemU6IGRlZmF1bHRCYXRjaFNpemUsXG4gICAgeWllbGRUaHJlc2hvbGQ6IGRlZmF1bHRZaWVsZFRocmVzaG9sZCxcbiAgICBzZXF1ZW50aWFsUHJvY2Vzc2luZzogZGVmYXVsdFNlcXVlbnRpYWxQcm9jZXNzaW5nLFxuICB9O1xufVxuXG4vKipcbiAqIFV0aWxpdHkgZnVuY3Rpb24gdG8gZGVmZXIgZXhlY3V0aW9uIHRvIHRoZSBuZXh0IHRpY2sgb2YgdGhlIGV2ZW50IGxvb3AuXG4gKiBUaGlzIHByZXZlbnRzIGJsb2NraW5nIHRoZSBldmVudCBsb29wIGR1cmluZyBoZWF2eSBiYXRjaCBvcGVyYXRpb25zIGJ5XG4gKiB5aWVsZGluZyBjb250cm9sIGJhY2sgdG8gdGhlIGV2ZW50IGxvb3AgdXNpbmcgc2V0SW1tZWRpYXRlLlxuICpcbiAqIEBwYXJhbSBzdGFydFRpbWUgLSBUaGUgdGltZXN0YW1wIHdoZW4gdGhlIGN1cnJlbnQgYmF0Y2ggcHJvY2Vzc2luZyBzdGFydGVkXG4gKiBAcGFyYW0geWllbGRUaHJlc2hvbGQgLSBUaW1lIHRocmVzaG9sZCBpbiBtaWxsaXNlY29uZHMgYmVmb3JlIHlpZWxkaW5nIGNvbnRyb2xcbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXIgYSB5aWVsZCBvY2N1cnJlZFxuICogQGludGVybmFsXG4gKi9cbmZ1bmN0aW9uIGRlZmVyKHN0YXJ0VGltZTogbnVtYmVyLCB5aWVsZFRocmVzaG9sZDogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIGNvbnN0IGVsYXBzZWQgPSBEYXRlLm5vdygpIC0gc3RhcnRUaW1lO1xuXG4gIC8vIE9ubHkgeWllbGQgaWYgd2UndmUgZXhjZWVkZWQgdGhlIHRocmVzaG9sZFxuICBpZiAoZWxhcHNlZCA+PSB5aWVsZFRocmVzaG9sZCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHJlc29sdmUodHJ1ZSkpO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gT3RoZXJ3aXNlIGNvbnRpbnVlIGltbWVkaWF0ZWx5XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoZmFsc2UpO1xufVxuXG4vKipcbiAqIEhlbHBlciB0byBnZXQgYmF0Y2ggcHJvY2Vzc2luZyBvcHRpb25zIHdpdGggZGVmYXVsdHMgYXBwbGllZFxuICogQHBhcmFtIG9wdGlvbnMgLSBVc2VyIHByb3ZpZGVkIG9wdGlvbnNcbiAqIEByZXR1cm5zIE9wdGlvbnMgd2l0aCBkZWZhdWx0cyBhcHBsaWVkXG4gKiBAaW50ZXJuYWxcbiAqL1xuZnVuY3Rpb24gZ2V0T3B0aW9ucyhvcHRpb25zPzogQmF0Y2hQcm9jZXNzaW5nT3B0aW9ucyk6IFJlcXVpcmVkPEJhdGNoUHJvY2Vzc2luZ09wdGlvbnM+IHtcbiAgY29uc3QgYmF0Y2hTaXplID0gb3B0aW9ucz8uYmF0Y2hTaXplID8/IGRlZmF1bHRCYXRjaFNpemU7XG4gIGNvbnN0IHlpZWxkVGhyZXNob2xkID0gb3B0aW9ucz8ueWllbGRUaHJlc2hvbGQgPz8gZGVmYXVsdFlpZWxkVGhyZXNob2xkO1xuICBjb25zdCBzZXF1ZW50aWFsUHJvY2Vzc2luZyA9IG9wdGlvbnM/LnNlcXVlbnRpYWxQcm9jZXNzaW5nID8/IGRlZmF1bHRTZXF1ZW50aWFsUHJvY2Vzc2luZztcblxuICBpZiAoIU51bWJlci5pc0ludGVnZXIoYmF0Y2hTaXplKSB8fCBiYXRjaFNpemUgPD0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignYmF0Y2hTaXplIG11c3QgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyJyk7XG4gIH1cbiAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKHlpZWxkVGhyZXNob2xkKSB8fCB5aWVsZFRocmVzaG9sZCA8IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3lpZWxkVGhyZXNob2xkIG11c3QgYmUgYSBub24tbmVnYXRpdmUgaW50ZWdlcicpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBiYXRjaFNpemUsXG4gICAgeWllbGRUaHJlc2hvbGQsXG4gICAgc2VxdWVudGlhbFByb2Nlc3NpbmcsXG4gIH07XG59XG5cbi8qKlxuICogSGVscGVyIHRvIHByb2Nlc3MgYW4gYXJyYXkgaW4gYmF0Y2hlcywgeWllbGRpbmcgYXMgbmVlZGVkLlxuICogQHBhcmFtIGl0ZW1zIC0gVGhlIGFycmF5IHRvIHByb2Nlc3NcbiAqIEBwYXJhbSBvcHRpb25zIC0gQmF0Y2ggcHJvY2Vzc2luZyBvcHRpb25zXG4gKiBAcGFyYW0gYmF0Y2hIYW5kbGVyIC0gRnVuY3Rpb24gdG8gaGFuZGxlIGVhY2ggYmF0Y2g6IChiYXRjaCwgYmF0Y2hTdGFydEluZGV4KSA9PiBQcm9taXNlPGFueT5cbiAqIEByZXR1cm5zIFByb21pc2U8dm9pZD5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gcHJvY2Vzc0luQmF0Y2hlczxUPihcbiAgaXRlbXM6IFRbXSxcbiAgb3B0aW9uczogUmVxdWlyZWQ8QmF0Y2hQcm9jZXNzaW5nT3B0aW9ucz4sXG4gIGJhdGNoSGFuZGxlcjogKGJhdGNoOiBUW10sIGJhdGNoU3RhcnQ6IG51bWJlcikgPT4gUHJvbWlzZTx2b2lkPixcbik6IFByb21pc2U8dm9pZD4ge1xuICBsZXQgaSA9IDA7XG4gIGxldCBzdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICBjb25zdCB7IGJhdGNoU2l6ZSB9ID0gb3B0aW9ucztcbiAgY29uc3QgbiA9IGl0ZW1zLmxlbmd0aDtcbiAgLy8gQWxsb2NhdGUgYSBzaW5nbGUgYmF0Y2ggYXJyYXkgYW5kIHJldXNlcyBpdCBmb3IgYWxsIGJhdGNoZXNcbiAgY29uc3QgYmF0Y2g6IFRbXSA9IEFycmF5KGJhdGNoU2l6ZSk7XG4gIHdoaWxlIChpIDwgbikge1xuICAgIGNvbnN0IGxlbiA9IE1hdGgubWluKGJhdGNoU2l6ZSwgbiAtIGkpO1xuICAgIGZvciAobGV0IGogPSAwOyBqIDwgbGVuOyBqICs9IDEpIHtcbiAgICAgIGJhdGNoW2pdID0gaXRlbXNbaSArIGpdO1xuICAgIH1cbiAgICBiYXRjaC5sZW5ndGggPSBsZW47XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWF3YWl0LWluLWxvb3BcbiAgICBhd2FpdCBiYXRjaEhhbmRsZXIoYmF0Y2gsIGkpO1xuICAgIGkgKz0gYmF0Y2hTaXplO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1hd2FpdC1pbi1sb29wXG4gICAgY29uc3QgZGlkWWllbGQgPSBhd2FpdCBkZWZlcihzdGFydFRpbWUsIG9wdGlvbnMueWllbGRUaHJlc2hvbGQpO1xuICAgIGlmIChkaWRZaWVsZCkgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgfVxufVxuXG4vKipcbiAqIE1hcHMgb3ZlciBhbiBhcnJheSBpbiBiYXRjaGVzIHRvIGF2b2lkIGJsb2NraW5nIHRoZSBldmVudCBsb29wLlxuICogUHJvY2Vzc2VzIGl0ZW1zIGluIGNodW5rcyBhbmQgeWllbGRzIGNvbnRyb2wgYmFjayB0byB0aGUgZXZlbnQgbG9vcCBiZXR3ZWVuIGJhdGNoZXNcbiAqIHdoZW4gdGhlIHByb2Nlc3NpbmcgdGltZSBleGNlZWRzIHRoZSB0aHJlc2hvbGQuXG4gKlxuICogQHRlbXBsYXRlIFQgLSBUaGUgdHlwZSBvZiBpdGVtcyBpbiB0aGUgaW5wdXQgYXJyYXlcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHR5cGUgb2YgaXRlbXMgaW4gdGhlIHJlc3VsdCBhcnJheVxuICogQHBhcmFtIGl0ZW1zIC0gVGhlIGFycmF5IHRvIG1hcCBvdmVyXG4gKiBAcGFyYW0gbWFwRm4gLSBUaGUgbWFwcGluZyBmdW5jdGlvbiB0byBhcHBseSB0byBlYWNoIGl0ZW0uIFJlY2VpdmVzIHRoZSBpdGVtIGFuZCBpdHMgaW5kZXguXG4gKiBAcGFyYW0gb3B0aW9ucyAtIEJhdGNoIHByb2Nlc3Npbmcgb3B0aW9uc1xuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIG1hcHBlZCBhcnJheVxuICogQHRocm93cyB7RXJyb3J9IFdoZW4gYmF0Y2hTaXplIGlzIG5vdCBhIHBvc2l0aXZlIGludGVnZXJcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gU3luY2hyb25vdXMgbWFwcGluZyB3aXRoIGRlZmF1bHQgb3B0aW9ucyAoc2VxdWVudGlhbCBwcm9jZXNzaW5nKVxuICogY29uc3QgZG91YmxlZCA9IGF3YWl0IG1hcEluQmF0Y2hlcyhbMSwgMiwgMywgNF0sICh4KSA9PiB4ICogMik7XG4gKlxuICogLy8gV2l0aCBjb25jdXJyZW50IHByb2Nlc3Npbmcgd2l0aGluIGJhdGNoZXNcbiAqIGNvbnN0IGRvdWJsZWQgPSBhd2FpdCBtYXBJbkJhdGNoZXMoWzEsIDIsIDMsIDRdLCAoeCkgPT4geCAqIDIsIHsgc2VxdWVudGlhbFByb2Nlc3Npbmc6IGZhbHNlIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXBJbkJhdGNoZXM8VCwgUj4oXG4gIGl0ZW1zOiBUW10sXG4gIG1hcEZuOiAoaXRlbTogVCwgaW5kZXg6IG51bWJlcikgPT4gUiB8IFByb21pc2U8Uj4sXG4gIG9wdGlvbnM/OiBCYXRjaFByb2Nlc3NpbmdPcHRpb25zLFxuKTogUHJvbWlzZTxSW10+IHtcbiAgY29uc3Qgb3B0cyA9IGdldE9wdGlvbnMob3B0aW9ucyk7XG5cbiAgcmV0dXJuIChhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0OiBSW10gPSBbXTtcbiAgICBhd2FpdCBwcm9jZXNzSW5CYXRjaGVzKGl0ZW1zLCBvcHRzLCBhc3luYyAoYmF0Y2gsIGJhdGNoU3RhcnQpID0+IHtcbiAgICAgIGlmIChvcHRzLnNlcXVlbnRpYWxQcm9jZXNzaW5nKSB7XG4gICAgICAgIC8vIFByb2Nlc3MgaXRlbXMgc2VxdWVudGlhbGx5XG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgYmF0Y2gubGVuZ3RoOyBqICs9IDEpIHtcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYXdhaXQtaW4tbG9vcCAtLSBzZXF1ZW50aWFsIHByb2Nlc3NpbmcgaXMgcmVxdWlyZWRcbiAgICAgICAgICBjb25zdCBtYXBwZWQgPSBhd2FpdCBtYXBGbihiYXRjaFtqXSwgYmF0Y2hTdGFydCArIGopO1xuICAgICAgICAgIHJlc3VsdC5wdXNoKG1hcHBlZCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFByb2Nlc3MgaXRlbXMgY29uY3VycmVudGx5XG4gICAgICAgIGNvbnN0IG1hcHBlZCA9IGF3YWl0IFByb21pc2UuYWxsKGJhdGNoLm1hcCgoaXRlbSwgaikgPT4gbWFwRm4oaXRlbSwgYmF0Y2hTdGFydCArIGopKSk7XG4gICAgICAgIHJlc3VsdC5wdXNoKC4uLm1hcHBlZCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSkoKTtcbn1cblxuLyoqXG4gKiBGaWx0ZXJzIGFuIGFycmF5IGluIGJhdGNoZXMgdG8gYXZvaWQgYmxvY2tpbmcgdGhlIGV2ZW50IGxvb3AuXG4gKiBQcm9jZXNzZXMgaXRlbXMgaW4gY2h1bmtzIGFuZCB5aWVsZHMgY29udHJvbCBiYWNrIHRvIHRoZSBldmVudCBsb29wIGJldHdlZW4gYmF0Y2hlc1xuICogd2hlbiB0aGUgcHJvY2Vzc2luZyB0aW1lIGV4Y2VlZHMgdGhlIHRocmVzaG9sZC5cbiAqXG4gKiBAdGVtcGxhdGUgVCAtIFRoZSB0eXBlIG9mIGl0ZW1zIGluIHRoZSBhcnJheVxuICogQHBhcmFtIGl0ZW1zIC0gVGhlIGFycmF5IHRvIGZpbHRlclxuICogQHBhcmFtIHByZWRpY2F0ZSAtIFRoZSBwcmVkaWNhdGUgZnVuY3Rpb24gdG8gdGVzdCBlYWNoIGl0ZW0uIFJlY2VpdmVzIHRoZSBpdGVtIGFuZCBpdHMgaW5kZXguXG4gKiBAcGFyYW0gb3B0aW9ucyAtIEJhdGNoIHByb2Nlc3Npbmcgb3B0aW9uc1xuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGZpbHRlcmVkIGFycmF5XG4gKiBAdGhyb3dzIHtFcnJvcn0gV2hlbiBiYXRjaFNpemUgaXMgbm90IGEgcG9zaXRpdmUgaW50ZWdlclxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBTeW5jaHJvbm91cyBmaWx0ZXJpbmcgd2l0aCBkZWZhdWx0IG9wdGlvbnNcbiAqIGNvbnN0IGV2ZW5zID0gYXdhaXQgZmlsdGVySW5CYXRjaGVzKFsxLCAyLCAzLCA0LCA1XSwgKHgpID0+IHggJSAyID09PSAwKTtcbiAqIC8vIFJlc3VsdDogWzIsIDRdXG4gKlxuICogLy8gV2l0aCBjdXN0b20gYmF0Y2ggc2l6ZVxuICogY29uc3QgZXZlbnMgPSBhd2FpdCBmaWx0ZXJJbkJhdGNoZXMoWzEsIDIsIDMsIDQsIDVdLCAoeCkgPT4geCAlIDIgPT09IDAsIHsgYmF0Y2hTaXplOiAyIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaWx0ZXJJbkJhdGNoZXM8VD4oXG4gIGl0ZW1zOiBUW10sXG4gIHByZWRpY2F0ZTogKGl0ZW06IFQsIGluZGV4OiBudW1iZXIpID0+IGJvb2xlYW4gfCBQcm9taXNlPGJvb2xlYW4+LFxuICBvcHRpb25zPzogQmF0Y2hQcm9jZXNzaW5nT3B0aW9ucyxcbik6IFByb21pc2U8VFtdPiB7XG4gIGNvbnN0IG9wdHMgPSBnZXRPcHRpb25zKG9wdGlvbnMpO1xuXG4gIHJldHVybiAoYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdDogVFtdID0gW107XG4gICAgYXdhaXQgcHJvY2Vzc0luQmF0Y2hlcyhpdGVtcywgb3B0cywgYXN5bmMgKGJhdGNoLCBiYXRjaFN0YXJ0KSA9PiB7XG4gICAgICBpZiAob3B0cy5zZXF1ZW50aWFsUHJvY2Vzc2luZykge1xuICAgICAgICAvLyBQcm9jZXNzIGl0ZW1zIHNlcXVlbnRpYWxseVxuICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGJhdGNoLmxlbmd0aDsgaiArPSAxKSB7XG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWF3YWl0LWluLWxvb3AgLS0gc2VxdWVudGlhbCBwcm9jZXNzaW5nIGlzIHJlcXVpcmVkXG4gICAgICAgICAgY29uc3QgcGFzc2VzID0gYXdhaXQgcHJlZGljYXRlKGJhdGNoW2pdLCBiYXRjaFN0YXJ0ICsgaik7XG4gICAgICAgICAgaWYgKHBhc3NlcykgcmVzdWx0LnB1c2goYmF0Y2hbal0pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBQcm9jZXNzIGl0ZW1zIGNvbmN1cnJlbnRseVxuICAgICAgICBjb25zdCBmbGFncyA9IGF3YWl0IFByb21pc2UuYWxsKGJhdGNoLm1hcCgoaXRlbSwgaikgPT4gcHJlZGljYXRlKGl0ZW0sIGJhdGNoU3RhcnQgKyBqKSkpO1xuICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGJhdGNoLmxlbmd0aDsgaiArPSAxKSB7XG4gICAgICAgICAgaWYgKGZsYWdzW2pdKSByZXN1bHQucHVzaChiYXRjaFtqXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9KSgpO1xufVxuXG4vKipcbiAqIEdyb3VwcyBhbiBhcnJheSBieSBhIGtleSBmdW5jdGlvbiBpbiBiYXRjaGVzIHRvIGF2b2lkIGJsb2NraW5nIHRoZSBldmVudCBsb29wLlxuICogUHJvY2Vzc2VzIGl0ZW1zIGluIGNodW5rcyBhbmQgeWllbGRzIGNvbnRyb2wgYmFjayB0byB0aGUgZXZlbnQgbG9vcCBiZXR3ZWVuIGJhdGNoZXNcbiAqIHdoZW4gdGhlIHByb2Nlc3NpbmcgdGltZSBleGNlZWRzIHRoZSB0aHJlc2hvbGQuXG4gKlxuICogQHRlbXBsYXRlIFQgLSBUaGUgdHlwZSBvZiBpdGVtcyBpbiB0aGUgYXJyYXlcbiAqIEB0ZW1wbGF0ZSBLIC0gVGhlIHR5cGUgb2YgdGhlIGdyb3VwaW5nIGtleSAobXVzdCBleHRlbmQgUHJvcGVydHlLZXkpXG4gKiBAcGFyYW0gaXRlbXMgLSBUaGUgYXJyYXkgdG8gZ3JvdXBcbiAqIEBwYXJhbSBrZXlGbiAtIFRoZSBmdW5jdGlvbiB0byBleHRyYWN0IHRoZSBncm91cGluZyBrZXkgZnJvbSBlYWNoIGl0ZW0uIFJlY2VpdmVzIHRoZSBpdGVtIGFuZCBpdHMgaW5kZXguXG4gKiBAcGFyYW0gb3B0aW9ucyAtIEJhdGNoIHByb2Nlc3Npbmcgb3B0aW9uc1xuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IHdpdGggZ3JvdXBlZCBpdGVtc1xuICogQHRocm93cyB7RXJyb3J9IFdoZW4gYmF0Y2hTaXplIGlzIG5vdCBhIHBvc2l0aXZlIGludGVnZXJcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gR3JvdXAgYnkgcHJvcGVydHkgd2l0aCBkZWZhdWx0IG9wdGlvbnNcbiAqIGNvbnN0IGJ5VHlwZSA9IGF3YWl0IGdyb3VwQnlJbkJhdGNoZXMoXG4gKiAgIFt7dHlwZTogJ0EnLCB2YWx1ZTogMX0sIHt0eXBlOiAnQicsIHZhbHVlOiAyfSwge3R5cGU6ICdBJywgdmFsdWU6IDN9XSxcbiAqICAgKGl0ZW0pID0+IGl0ZW0udHlwZVxuICogKTtcbiAqIC8vIFJlc3VsdDoge0E6IFt7dHlwZTogJ0EnLCB2YWx1ZTogMX0sIHt0eXBlOiAnQScsIHZhbHVlOiAzfV0sIEI6IFt7dHlwZTogJ0InLCB2YWx1ZTogMn1dfVxuICpcbiAqIC8vIFdpdGggY3VzdG9tIGJhdGNoIHNpemVcbiAqIGNvbnN0IGJ5VHlwZSA9IGF3YWl0IGdyb3VwQnlJbkJhdGNoZXMoXG4gKiAgIFt7dHlwZTogJ0EnLCB2YWx1ZTogMX0sIHt0eXBlOiAnQicsIHZhbHVlOiAyfSwge3R5cGU6ICdBJywgdmFsdWU6IDN9XSxcbiAqICAgKGl0ZW0pID0+IGl0ZW0udHlwZSxcbiAqICAgeyBiYXRjaFNpemU6IDIgfVxuICogKTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ3JvdXBCeUluQmF0Y2hlczxULCBLIGV4dGVuZHMgUHJvcGVydHlLZXk+KFxuICBpdGVtczogVFtdLFxuICBrZXlGbjogKGl0ZW06IFQsIGluZGV4OiBudW1iZXIpID0+IEsgfCBQcm9taXNlPEs+LFxuICBvcHRpb25zPzogQmF0Y2hQcm9jZXNzaW5nT3B0aW9ucyxcbik6IFByb21pc2U8UmVjb3JkPEssIFRbXT4+IHtcbiAgY29uc3Qgb3B0cyA9IGdldE9wdGlvbnMob3B0aW9ucyk7XG5cbiAgcmV0dXJuIChhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8SywgVFtdPiA9IHt9IGFzIFJlY29yZDxLLCBUW10+O1xuICAgIGF3YWl0IHByb2Nlc3NJbkJhdGNoZXMoaXRlbXMsIG9wdHMsIGFzeW5jIChiYXRjaCwgYmF0Y2hTdGFydCkgPT4ge1xuICAgICAgaWYgKG9wdHMuc2VxdWVudGlhbFByb2Nlc3NpbmcpIHtcbiAgICAgICAgLy8gUHJvY2VzcyBpdGVtcyBzZXF1ZW50aWFsbHlcbiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBiYXRjaC5sZW5ndGg7IGogKz0gMSkge1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1hd2FpdC1pbi1sb29wIC0tIHNlcXVlbnRpYWwgcHJvY2Vzc2luZyBpcyByZXF1aXJlZFxuICAgICAgICAgIGNvbnN0IGtleSA9IGF3YWl0IGtleUZuKGJhdGNoW2pdLCBiYXRjaFN0YXJ0ICsgaik7XG4gICAgICAgICAgaWYgKCFyZXN1bHRba2V5XSkgcmVzdWx0W2tleV0gPSBbXTtcbiAgICAgICAgICByZXN1bHRba2V5XS5wdXNoKGJhdGNoW2pdKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gUHJvY2VzcyBpdGVtcyBjb25jdXJyZW50bHlcbiAgICAgICAgY29uc3Qga2V5cyA9IGF3YWl0IFByb21pc2UuYWxsKGJhdGNoLm1hcCgoaXRlbSwgaikgPT4ga2V5Rm4oaXRlbSwgYmF0Y2hTdGFydCArIGopKSk7XG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgYmF0Y2gubGVuZ3RoOyBqICs9IDEpIHtcbiAgICAgICAgICBjb25zdCBrZXkgPSBrZXlzW2pdO1xuICAgICAgICAgIGlmICghcmVzdWx0W2tleV0pIHJlc3VsdFtrZXldID0gW107XG4gICAgICAgICAgcmVzdWx0W2tleV0ucHVzaChiYXRjaFtqXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9KSgpO1xufVxuXG4vKipcbiAqIFJlZHVjZXMgYW4gYXJyYXkgaW4gYmF0Y2hlcyB0byBhdm9pZCBibG9ja2luZyB0aGUgZXZlbnQgbG9vcC5cbiAqIFByb2Nlc3NlcyBpdGVtcyBpbiBjaHVua3MgYW5kIHlpZWxkcyBjb250cm9sIGJhY2sgdG8gdGhlIGV2ZW50IGxvb3AgYmV0d2VlbiBiYXRjaGVzXG4gKiB3aGVuIHRoZSBwcm9jZXNzaW5nIHRpbWUgZXhjZWVkcyB0aGUgdGhyZXNob2xkLiBTZXF1ZW50aWFsIHByb2Nlc3NpbmcgaXMgYWx3YXlzIHVzZWQgZm9yIHRoZSByZWR1Y2VyIGZ1bmN0aW9uLFxuICogaXJyZXNwZWN0aXZlIG9mIHRoZSBgc2VxdWVudGlhbFByb2Nlc3NpbmdgIG9wdGlvbi5cbiAqXG4gKiBAdGVtcGxhdGUgVCAtIFRoZSB0eXBlIG9mIGl0ZW1zIGluIHRoZSBhcnJheVxuICogQHRlbXBsYXRlIFIgLSBUaGUgdHlwZSBvZiB0aGUgYWNjdW11bGF0b3IvcmVzdWx0XG4gKiBAcGFyYW0gaXRlbXMgLSBUaGUgYXJyYXkgdG8gcmVkdWNlXG4gKiBAcGFyYW0gcmVkdWNlciAtIFRoZSByZWR1Y2VyIGZ1bmN0aW9uLiBSZWNlaXZlcyB0aGUgYWNjdW11bGF0b3IsIGN1cnJlbnQgaXRlbSwgYW5kIGluZGV4LlxuICogQHBhcmFtIGluaXRpYWxWYWx1ZSAtIFRoZSBpbml0aWFsIHZhbHVlIGZvciB0aGUgYWNjdW11bGF0b3JcbiAqIEBwYXJhbSBvcHRpb25zIC0gQmF0Y2ggcHJvY2Vzc2luZyBvcHRpb25zXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgcmVkdWNlZCB2YWx1ZVxuICogQHRocm93cyB7RXJyb3J9IFdoZW4gYmF0Y2hTaXplIGlzIG5vdCBhIHBvc2l0aXZlIGludGVnZXJcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gU3VtIG51bWJlcnMgd2l0aCBkZWZhdWx0IG9wdGlvbnNcbiAqIGNvbnN0IHN1bSA9IGF3YWl0IHJlZHVjZUluQmF0Y2hlcyhbMSwgMiwgMywgNF0sIChhY2MsIHgpID0+IGFjYyArIHgsIDApO1xuICogLy8gUmVzdWx0OiAxMFxuICpcbiAqIC8vIFdpdGggY3VzdG9tIGJhdGNoIHNpemVcbiAqIGNvbnN0IHN1bSA9IGF3YWl0IHJlZHVjZUluQmF0Y2hlcyhbMSwgMiwgMywgNF0sIChhY2MsIHgpID0+IGFjYyArIHgsIDAsIHsgYmF0Y2hTaXplOiAyIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWR1Y2VJbkJhdGNoZXM8VCwgUj4oXG4gIGl0ZW1zOiBUW10sXG4gIHJlZHVjZXI6IChhY2M6IFIsIGl0ZW06IFQsIGluZGV4OiBudW1iZXIpID0+IFIgfCBQcm9taXNlPFI+LFxuICBpbml0aWFsVmFsdWU6IFIsXG4gIG9wdGlvbnM/OiBCYXRjaFByb2Nlc3NpbmdPcHRpb25zLFxuKTogUHJvbWlzZTxSPiB7XG4gIGNvbnN0IG9wdHMgPSBnZXRPcHRpb25zKG9wdGlvbnMpO1xuXG4gIHJldHVybiAoYXN5bmMgKCkgPT4ge1xuICAgIGxldCBhY2MgPSBpbml0aWFsVmFsdWU7XG4gICAgYXdhaXQgcHJvY2Vzc0luQmF0Y2hlcyhpdGVtcywgb3B0cywgYXN5bmMgKGJhdGNoLCBiYXRjaFN0YXJ0KSA9PiB7XG4gICAgICAvLyBBbHdheXMgc2VxdWVudGlhbCwgcmVnYXJkbGVzcyBvZiBzZXF1ZW50aWFsUHJvY2Vzc2luZyBvcHRpb25cbiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgYmF0Y2gubGVuZ3RoOyBqICs9IDEpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWF3YWl0LWluLWxvb3AgLS0gc2VxdWVudGlhbCBwcm9jZXNzaW5nIGlzIHJlcXVpcmVkXG4gICAgICAgIGFjYyA9IGF3YWl0IHJlZHVjZXIoYWNjLCBiYXRjaFtqXSwgYmF0Y2hTdGFydCArIGopO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBhY2M7XG4gIH0pKCk7XG59XG5cbi8qKlxuICogRmxhdE1hcHMgYW4gYXJyYXkgaW4gYmF0Y2hlcyB0byBhdm9pZCBibG9ja2luZyB0aGUgZXZlbnQgbG9vcC5cbiAqIFByb2Nlc3NlcyBpdGVtcyBpbiBjaHVua3MsIGZsYXR0ZW5zIHRoZSByZXN1bHRzLCBhbmQgeWllbGRzIGNvbnRyb2wgYmFjayB0byB0aGUgZXZlbnQgbG9vcCBiZXR3ZWVuIGJhdGNoZXNcbiAqIHdoZW4gdGhlIHByb2Nlc3NpbmcgdGltZSBleGNlZWRzIHRoZSB0aHJlc2hvbGQuXG4gKlxuICogQHRlbXBsYXRlIFQgLSBUaGUgdHlwZSBvZiBpdGVtcyBpbiB0aGUgaW5wdXQgYXJyYXlcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHR5cGUgb2YgaXRlbXMgaW4gdGhlIGZsYXR0ZW5lZCByZXN1bHQgYXJyYXlcbiAqIEBwYXJhbSBpdGVtcyAtIFRoZSBhcnJheSB0byBmbGF0TWFwIG92ZXJcbiAqIEBwYXJhbSBtYXBGbiAtIFRoZSBtYXBwaW5nIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhbiBhcnJheSBmb3IgZWFjaCBpdGVtLiBSZWNlaXZlcyB0aGUgaXRlbSBhbmQgaXRzIGluZGV4LlxuICogQHBhcmFtIG9wdGlvbnMgLSBCYXRjaCBwcm9jZXNzaW5nIG9wdGlvbnNcbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBmbGF0dGVuZWQgbWFwcGVkIGFycmF5XG4gKiBAdGhyb3dzIHtFcnJvcn0gV2hlbiBiYXRjaFNpemUgaXMgbm90IGEgcG9zaXRpdmUgaW50ZWdlclxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBEdXBsaWNhdGUgZWFjaCBpdGVtIHdpdGggZGVmYXVsdCBvcHRpb25zXG4gKiBjb25zdCBkdXBsaWNhdGVkID0gYXdhaXQgZmxhdE1hcEluQmF0Y2hlcyhbMSwgMiwgM10sICh4KSA9PiBbeCwgeF0pO1xuICogLy8gUmVzdWx0OiBbMSwgMSwgMiwgMiwgMywgM11cbiAqXG4gKiAvLyBXaXRoIGN1c3RvbSBiYXRjaCBzaXplXG4gKiBjb25zdCBkdXBsaWNhdGVkID0gYXdhaXQgZmxhdE1hcEluQmF0Y2hlcyhbMSwgMiwgM10sICh4KSA9PiBbeCwgeF0sIHsgYmF0Y2hTaXplOiAyIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbGF0TWFwSW5CYXRjaGVzPFQsIFI+KFxuICBpdGVtczogVFtdLFxuICBtYXBGbjogKGl0ZW06IFQsIGluZGV4OiBudW1iZXIpID0+IFJbXSB8IFByb21pc2U8UltdPixcbiAgb3B0aW9ucz86IEJhdGNoUHJvY2Vzc2luZ09wdGlvbnMsXG4pOiBQcm9taXNlPFJbXT4ge1xuICBjb25zdCBvcHRzID0gZ2V0T3B0aW9ucyhvcHRpb25zKTtcblxuICByZXR1cm4gKGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXN1bHQ6IFJbXSA9IFtdO1xuICAgIGF3YWl0IHByb2Nlc3NJbkJhdGNoZXMoaXRlbXMsIG9wdHMsIGFzeW5jIChiYXRjaCwgYmF0Y2hTdGFydCkgPT4ge1xuICAgICAgaWYgKG9wdHMuc2VxdWVudGlhbFByb2Nlc3NpbmcpIHtcbiAgICAgICAgLy8gUHJvY2VzcyBpdGVtcyBzZXF1ZW50aWFsbHlcbiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBiYXRjaC5sZW5ndGg7IGogKz0gMSkge1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1hd2FpdC1pbi1sb29wIC0tIHNlcXVlbnRpYWwgcHJvY2Vzc2luZyBpcyByZXF1aXJlZFxuICAgICAgICAgIGNvbnN0IG1hcHBlZCA9IGF3YWl0IG1hcEZuKGJhdGNoW2pdLCBiYXRjaFN0YXJ0ICsgaik7XG4gICAgICAgICAgcmVzdWx0LnB1c2goLi4ubWFwcGVkKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gUHJvY2VzcyBpdGVtcyBjb25jdXJyZW50bHlcbiAgICAgICAgY29uc3QgbWFwcGVkID0gYXdhaXQgUHJvbWlzZS5hbGwoYmF0Y2gubWFwKChpdGVtLCBqKSA9PiBtYXBGbihpdGVtLCBiYXRjaFN0YXJ0ICsgaikpKTtcbiAgICAgICAgbWFwcGVkLmZvckVhY2goKGFycikgPT4ge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKC4uLmFycik7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH0pKCk7XG59XG5cbi8qKlxuICogZm9yRWFjaCBvdmVyIGFuIGFycmF5IGluIGJhdGNoZXMgdG8gYXZvaWQgYmxvY2tpbmcgdGhlIGV2ZW50IGxvb3AuXG4gKiBQcm9jZXNzZXMgaXRlbXMgaW4gY2h1bmtzIGFuZCB5aWVsZHMgY29udHJvbCBiYWNrIHRvIHRoZSBldmVudCBsb29wIGJldHdlZW4gYmF0Y2hlc1xuICogd2hlbiB0aGUgcHJvY2Vzc2luZyB0aW1lIGV4Y2VlZHMgdGhlIHRocmVzaG9sZC5cbiAqXG4gKiBAdGVtcGxhdGUgVCAtIFRoZSB0eXBlIG9mIGl0ZW1zIGluIHRoZSBpbnB1dCBhcnJheVxuICogQHBhcmFtIGl0ZW1zIC0gVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3ZlclxuICogQHBhcmFtIGZuIC0gVGhlIGZ1bmN0aW9uIHRvIGFwcGx5IHRvIGVhY2ggaXRlbS4gUmVjZWl2ZXMgdGhlIGl0ZW0gYW5kIGl0cyBpbmRleC4gQ2FuIGJlIGFzeW5jLlxuICogQHBhcmFtIG9wdGlvbnMgLSBCYXRjaCBwcm9jZXNzaW5nIG9wdGlvbnNcbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gYWxsIGl0ZW1zIGhhdmUgYmVlbiBwcm9jZXNzZWRcbiAqIEB0aHJvd3Mge0Vycm9yfSBXaGVuIGJhdGNoU2l6ZSBpcyBub3QgYSBwb3NpdGl2ZSBpbnRlZ2VyXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIFByb2Nlc3MgaXRlbXMgaW4gYmF0Y2hlcyB3aXRoIGRlZmF1bHQgb3B0aW9uc1xuICogYXdhaXQgZm9yRWFjaEluQmF0Y2hlcyhbMSwgMiwgMywgNF0sIGFzeW5jICh4KSA9PiB7XG4gKiAgIGF3YWl0IGRvU29tZXRoaW5nKHgpO1xuICogfSk7XG4gKlxuICogLy8gV2l0aCBjdXN0b20gYmF0Y2ggc2l6ZVxuICogYXdhaXQgZm9yRWFjaEluQmF0Y2hlcyhbMSwgMiwgMywgNF0sIGFzeW5jICh4KSA9PiB7XG4gKiAgIGF3YWl0IGRvU29tZXRoaW5nKHgpO1xuICogfSwgeyBiYXRjaFNpemU6IDIgfSk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZvckVhY2hJbkJhdGNoZXM8VD4oXG4gIGl0ZW1zOiBUW10sXG4gIGZuOiAoaXRlbTogVCwgaW5kZXg6IG51bWJlcikgPT4gdm9pZCB8IFByb21pc2U8dm9pZD4sXG4gIG9wdGlvbnM/OiBCYXRjaFByb2Nlc3NpbmdPcHRpb25zLFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IG9wdHMgPSBnZXRPcHRpb25zKG9wdGlvbnMpO1xuXG4gIHJldHVybiBwcm9jZXNzSW5CYXRjaGVzKGl0ZW1zLCBvcHRzLCBhc3luYyAoYmF0Y2gsIGJhdGNoU3RhcnQpID0+IHtcbiAgICBpZiAob3B0cy5zZXF1ZW50aWFsUHJvY2Vzc2luZykge1xuICAgICAgLy8gUHJvY2VzcyBpdGVtcyBzZXF1ZW50aWFsbHlcbiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgYmF0Y2gubGVuZ3RoOyBqICs9IDEpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWF3YWl0LWluLWxvb3AgLS0gc2VxdWVudGlhbCBwcm9jZXNzaW5nIGlzIHJlcXVpcmVkXG4gICAgICAgIGF3YWl0IGZuKGJhdGNoW2pdLCBiYXRjaFN0YXJ0ICsgaik7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFByb2Nlc3MgaXRlbXMgY29uY3VycmVudGx5XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChiYXRjaC5tYXAoKGl0ZW0sIGopID0+IGZuKGl0ZW0sIGJhdGNoU3RhcnQgKyBqKSkpO1xuICAgIH1cbiAgfSk7XG59XG4iXX0=
|