@rudderstack/integrations-lib 0.2.33 → 0.2.34
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/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/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch-processing.bench.d.ts","sourceRoot":"","sources":["../../src/utils/batch-processing.bench.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/* eslint-disable no-console */
|
|
7
|
+
const node_perf_hooks_1 = require("node:perf_hooks");
|
|
8
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
9
|
+
const batch_processing_1 = require("./batch-processing");
|
|
10
|
+
async function bench(fn, label, iterations = 5) {
|
|
11
|
+
let total = 0;
|
|
12
|
+
for (let i = 0; i < iterations; i += 1) {
|
|
13
|
+
const start = node_perf_hooks_1.performance.now();
|
|
14
|
+
// eslint-disable-next-line no-await-in-loop
|
|
15
|
+
await fn();
|
|
16
|
+
total += node_perf_hooks_1.performance.now() - start;
|
|
17
|
+
}
|
|
18
|
+
const avg = total / iterations;
|
|
19
|
+
console.log(`${label}: avg ${avg.toFixed(2)} ms over ${iterations} runs`);
|
|
20
|
+
return avg;
|
|
21
|
+
}
|
|
22
|
+
async function section(title, fn) {
|
|
23
|
+
console.log(`\n=== ${title} ===`);
|
|
24
|
+
await fn();
|
|
25
|
+
}
|
|
26
|
+
async function runBenchmarks() {
|
|
27
|
+
const arr = Array.from({ length: 10_000 }, (_, i) => i);
|
|
28
|
+
console.log(`Running benchmarks on array of length ${arr.length}`);
|
|
29
|
+
await section('map', async () => {
|
|
30
|
+
await bench(() => (0, batch_processing_1.mapInBatches)(arr, (x) => x + 1, { batchSize: 20, yieldThreshold: 10 }), 'mapInBatches { batchSize: 20, yieldThreshold: 10 }');
|
|
31
|
+
await bench(() => (0, batch_processing_1.mapInBatches)(arr, (x) => x + 1, {
|
|
32
|
+
batchSize: 20,
|
|
33
|
+
yieldThreshold: 10,
|
|
34
|
+
sequentialProcessing: false,
|
|
35
|
+
}), 'mapInBatches { batchSize: 20, yieldThreshold: 10, sequentialProcessing: false }');
|
|
36
|
+
await bench(() => Promise.resolve(lodash_1.default.map(arr, (x) => x + 1)), 'lodash.map');
|
|
37
|
+
await bench(() => Promise.resolve(arr.map((x) => x + 1)), 'Array.prototype.map');
|
|
38
|
+
});
|
|
39
|
+
await section('filter', async () => {
|
|
40
|
+
await bench(() => (0, batch_processing_1.filterInBatches)(arr, (x) => x % 2 === 0, { batchSize: 20, yieldThreshold: 10 }), 'filterInBatches { batchSize: 20, yieldThreshold: 10 }');
|
|
41
|
+
await bench(() => (0, batch_processing_1.filterInBatches)(arr, (x) => x % 2 === 0, {
|
|
42
|
+
batchSize: 20,
|
|
43
|
+
yieldThreshold: 10,
|
|
44
|
+
sequentialProcessing: false,
|
|
45
|
+
}), 'filterInBatches { batchSize: 20, yieldThreshold: 10, sequentialProcessing: false }');
|
|
46
|
+
await bench(() => Promise.resolve(lodash_1.default.filter(arr, (x) => x % 2 === 0)), 'lodash.filter');
|
|
47
|
+
await bench(() => Promise.resolve(arr.filter((x) => x % 2 === 0)), 'Array.prototype.filter');
|
|
48
|
+
});
|
|
49
|
+
await section('groupBy', async () => {
|
|
50
|
+
await bench(() => (0, batch_processing_1.groupByInBatches)(arr, (x) => (x % 2 === 0 ? 'even' : 'odd'), {
|
|
51
|
+
batchSize: 20,
|
|
52
|
+
yieldThreshold: 10,
|
|
53
|
+
}), 'groupByInBatches { batchSize: 20, yieldThreshold: 10 }');
|
|
54
|
+
await bench(() => (0, batch_processing_1.groupByInBatches)(arr, (x) => (x % 2 === 0 ? 'even' : 'odd'), {
|
|
55
|
+
batchSize: 20,
|
|
56
|
+
yieldThreshold: 10,
|
|
57
|
+
sequentialProcessing: false,
|
|
58
|
+
}), 'groupByInBatches { batchSize: 20, yieldThreshold: 10, sequentialProcessing: false }');
|
|
59
|
+
await bench(() => Promise.resolve(lodash_1.default.groupBy(arr, (x) => (x % 2 === 0 ? 'even' : 'odd'))), 'lodash.groupBy');
|
|
60
|
+
});
|
|
61
|
+
await section('reduce', async () => {
|
|
62
|
+
await bench(() => (0, batch_processing_1.reduceInBatches)(arr, (acc, x) => acc + x, 0, { batchSize: 20, yieldThreshold: 10 }), 'reduceInBatches { batchSize: 20, yieldThreshold: 10 }');
|
|
63
|
+
await bench(() => Promise.resolve(lodash_1.default.reduce(arr, (acc, x) => acc + x, 0)), 'lodash.reduce');
|
|
64
|
+
await bench(() => Promise.resolve(arr.reduce((acc, x) => acc + x, 0)), 'Array.prototype.reduce');
|
|
65
|
+
});
|
|
66
|
+
await section('flatMap', async () => {
|
|
67
|
+
await bench(() => (0, batch_processing_1.flatMapInBatches)(arr, (x) => [x, x], { batchSize: 20, yieldThreshold: 10 }), 'flatMapInBatches { batchSize: 20, yieldThreshold: 10 }');
|
|
68
|
+
await bench(() => (0, batch_processing_1.flatMapInBatches)(arr, (x) => [x, x], {
|
|
69
|
+
batchSize: 20,
|
|
70
|
+
yieldThreshold: 10,
|
|
71
|
+
sequentialProcessing: false,
|
|
72
|
+
}), 'flatMapInBatches { batchSize: 20, yieldThreshold: 10, sequentialProcessing: false }');
|
|
73
|
+
await bench(() => Promise.resolve(lodash_1.default.flatMap(arr, (x) => [x, x])), 'lodash.flatMap');
|
|
74
|
+
await bench(() => Promise.resolve(arr.flatMap
|
|
75
|
+
? arr.flatMap((x) => [x, x])
|
|
76
|
+
: [].concat(...arr.map((x) => [x, x]))), 'Array.prototype.flatMap');
|
|
77
|
+
});
|
|
78
|
+
await section('forEach', async () => {
|
|
79
|
+
await bench(() => (0, batch_processing_1.forEachInBatches)(arr, () => { }, { batchSize: 20, yieldThreshold: 10 }), 'forEachInBatches { batchSize: 20, yieldThreshold: 10 }');
|
|
80
|
+
await bench(() => (0, batch_processing_1.forEachInBatches)(arr, () => { }, {
|
|
81
|
+
batchSize: 20,
|
|
82
|
+
yieldThreshold: 10,
|
|
83
|
+
sequentialProcessing: false,
|
|
84
|
+
}), 'forEachInBatches { batchSize: 20, yieldThreshold: 10, sequentialProcessing: false }');
|
|
85
|
+
await bench(() => Promise.resolve(arr.forEach(() => { })), 'Array.prototype.forEach');
|
|
86
|
+
await bench(() => Promise.resolve(lodash_1.default.forEach(arr, () => { })), 'lodash.forEach');
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
// to run benchmarks use: npx ts-node src/utils/batch-processing.bench.ts
|
|
90
|
+
if (require.main === module) {
|
|
91
|
+
runBenchmarks().catch((err) => {
|
|
92
|
+
console.error(err);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmF0Y2gtcHJvY2Vzc2luZy5iZW5jaC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9iYXRjaC1wcm9jZXNzaW5nLmJlbmNoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsK0JBQStCO0FBQy9CLHFEQUE4QztBQUM5QyxvREFBNEI7QUFDNUIseURBTzRCO0FBRTVCLEtBQUssVUFBVSxLQUFLLENBQ2xCLEVBQW9DLEVBQ3BDLEtBQWEsRUFDYixVQUFVLEdBQUcsQ0FBQztJQUVkLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQztJQUNkLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxVQUFVLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ3ZDLE1BQU0sS0FBSyxHQUFHLDZCQUFXLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDaEMsNENBQTRDO1FBQzVDLE1BQU0sRUFBRSxFQUFFLENBQUM7UUFDWCxLQUFLLElBQUksNkJBQVcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxLQUFLLENBQUM7SUFDckMsQ0FBQztJQUNELE1BQU0sR0FBRyxHQUFHLEtBQUssR0FBRyxVQUFVLENBQUM7SUFDL0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssU0FBUyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxZQUFZLFVBQVUsT0FBTyxDQUFDLENBQUM7SUFDMUUsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDO0FBRUQsS0FBSyxVQUFVLE9BQU8sQ0FBQyxLQUFhLEVBQUUsRUFBdUI7SUFDM0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLEtBQUssTUFBTSxDQUFDLENBQUM7SUFDbEMsTUFBTSxFQUFFLEVBQUUsQ0FBQztBQUNiLENBQUM7QUFFRCxLQUFLLFVBQVUsYUFBYTtJQUMxQixNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFB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QUFFLEdBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSx5QkFBeUIsQ0FBQyxDQUFDO1FBQ3JGLE1BQU0sS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsZ0JBQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztJQUN0RixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCx5RUFBeUU7QUFDekUsSUFBSSxPQUFPLENBQUMsSUFBSSxLQUFLLE1BQU0sRUFBRSxDQUFDO0lBQzVCLGFBQWEsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO1FBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbkIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsQixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5pbXBvcnQgeyBwZXJmb3JtYW5jZSB9IGZyb20gJ25vZGU6cGVyZl9ob29rcyc7XG5pbXBvcnQgbG9kYXNoIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQge1xuICBtYXBJbkJhdGNoZXMsXG4gIGZpbHRlckluQmF0Y2hlcyxcbiAgZ3JvdXBCeUluQmF0Y2hlcyxcbiAgcmVkdWNlSW5CYXRjaGVzLFxuICBmbGF0TWFwSW5CYXRjaGVzLFxuICBmb3JFYWNoSW5CYXRjaGVzLFxufSBmcm9tICcuL2JhdGNoLXByb2Nlc3NpbmcnO1xuXG5hc3luYyBmdW5jdGlvbiBiZW5jaChcbiAgZm46ICgpID0+IFByb21pc2U8dW5rbm93bj4gfCB1bmtub3duLFxuICBsYWJlbDogc3RyaW5nLFxuICBpdGVyYXRpb25zID0gNSxcbik6IFByb21pc2U8bnVtYmVyPiB7XG4gIGxldCB0b3RhbCA9IDA7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgaXRlcmF0aW9uczsgaSArPSAxKSB7XG4gICAgY29uc3Qgc3RhcnQgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYXdhaXQtaW4tbG9vcFxuICAgIGF3YWl0IGZuKCk7XG4gICAgdG90YWwgKz0gcGVyZm9ybWFuY2Uubm93KCkgLSBzdGFydDtcbiAgfVxuICBjb25zdCBhdmcgPSB0b3RhbCAvIGl0ZXJhdGlvbnM7XG4gIGNvbnNvbGUubG9nKGAke2xhYmVsfTogYXZnICR7YXZnLnRvRml4ZWQoMil9IG1zIG92ZXIgJHtpdGVyYXRpb25zfSBydW5zYCk7XG4gIHJldHVybiBhdmc7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNlY3Rpb24odGl0bGU6IHN0cmluZywgZm46ICgpID0+IFByb21pc2U8dm9pZD4pIHtcbiAgY29uc29sZS5sb2coYFxcbj09PSAke3RpdGxlfSA9PT1gKTtcbiAgYXdhaXQgZm4oKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcnVuQmVuY2htYXJrcygpIHtcbiAgY29uc3QgYXJyID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogMTBfMDAwIH0sIChfLCBpKSA9PiBpKTtcblxuICBjb25zb2xlLmxvZyhgUnVubmluZyBiZW5jaG1hcmtzIG9uIGFycmF5IG9mIGxlbmd0aCAke2Fyci5sZW5ndGh9YCk7XG5cbiAgYXdhaXQgc2VjdGlvbignbWFwJywgYXN5bmMgKCkgPT4ge1xuICAgIGF3YWl0IGJlbmNoKFxuICAgICAgKCkgPT4gbWFwSW5CYXRjaGVzKGFyciwgKHgpID0+IHggKyAxLCB7IGJhdGNoU2l6ZTogMjAsIHlpZWxkVGhyZXNob2xkOiAxMCB9KSxcbiAgICAgICdtYXBJbkJhdGNoZXMgeyBiYXRjaFNpemU6IDIwLCB5aWVsZFRocmVzaG9sZDogMTAgfScsXG4gICAgKTtcbiAgICBhd2FpdCBiZW5jaChcbiAgICAgICgpID0+XG4gICAgICAgIG1hcEluQmF0Y2hlcyhhcnIsICh4KSA9PiB4ICsgMSwge1xuICAgICAgICAgIGJhdGNoU2l6ZTogMjAsXG4gICAgICAgICAgeWllbGRUaHJlc2hvbGQ6IDEwLFxuICAgICAgICAgIHNlcXVlbnRpYWxQcm9jZXNzaW5nOiBmYWxzZSxcbiAgICAgICAgfSksXG4gICAgICAnbWFwSW5CYXRjaGVzIHsgYmF0Y2hTaXplOiAyMCwgeWllbGRUaHJlc2hvbGQ6IDEwLCBzZXF1ZW50aWFsUHJvY2Vzc2luZzogZmFsc2UgfScsXG4gICAgKTtcbiAgICBhd2FpdCBiZW5jaCgoKSA9PiBQcm9taXNlLnJlc29sdmUobG9kYXNoLm1hcChhcnIsICh4KSA9PiB4ICsgMSkpLCAnbG9kYXNoLm1hcCcpO1xuICAgIGF3YWl0IGJlbmNoKCgpID0+IFByb21pc2UucmVzb2x2ZShhcnIubWFwKCh4KSA9PiB4ICsgMSkpLCAnQXJyYXkucHJvdG90eXBlLm1hcCcpO1xuICB9KTtcblxuICBhd2FpdCBzZWN0aW9uKCdmaWx0ZXInLCBhc3luYyAoKSA9PiB7XG4gICAgYXdhaXQgYmVuY2goXG4gICAgICAoKSA9PiBmaWx0ZXJJbkJhdGNoZXMoYXJyLCAoeCkgPT4geCAlIDIgPT09IDAsIHsgYmF0Y2hTaXplOiAyMCwgeWllbGRUaHJlc2hvbGQ6IDEwIH0pLFxuICAgICAgJ2ZpbHRlckluQmF0Y2hlcyB7IGJhdGNoU2l6ZTogMjAsIHlpZWxkVGhyZXNob2xkOiAxMCB9JyxcbiAgICApO1xuICAgIGF3YWl0IGJlbmNoKFxuICAgICAgKCkgPT5cbiAgICAgICAgZmlsdGVySW5CYXRjaGVzKGFyciwgKHgpID0+IHggJSAyID09PSAwLCB7XG4gICAgICAgICAgYmF0Y2hTaXplOiAyMCxcbiAgICAgICAgICB5aWVsZFRocmVzaG9sZDogMTAsXG4gICAgICAgICAgc2VxdWVudGlhbFByb2Nlc3Npbmc6IGZhbHNlLFxuICAgICAgICB9KSxcbiAgICAgICdmaWx0ZXJJbkJhdGNoZXMgeyBiYXRjaFNpemU6IDIwLCB5aWVsZFRocmVzaG9sZDogMTAsIHNlcXVlbnRpYWxQcm9jZXNzaW5nOiBmYWxzZSB9JyxcbiAgICApO1xuICAgIGF3YWl0IGJlbmNoKCgpID0+IFByb21pc2UucmVzb2x2ZShsb2Rhc2guZmlsdGVyKGFyciwgKHgpID0+IHggJSAyID09PSAwKSksICdsb2Rhc2guZmlsdGVyJyk7XG4gICAgYXdhaXQgYmVuY2goKCkgPT4gUHJvbWlzZS5yZXNvbHZlKGFyci5maWx0ZXIoKHgpID0+IHggJSAyID09PSAwKSksICdBcnJheS5wcm90b3R5cGUuZmlsdGVyJyk7XG4gIH0pO1xuXG4gIGF3YWl0IHNlY3Rpb24oJ2dyb3VwQnknLCBhc3luYyAoKSA9PiB7XG4gICAgYXdhaXQgYmVuY2goXG4gICAgICAoKSA9PlxuICAgICAgICBncm91cEJ5SW5CYXRjaGVzKGFyciwgKHgpID0+ICh4ICUgMiA9PT0gMCA/ICdldmVuJyA6ICdvZGQnKSwge1xuICAgICAgICAgIGJhdGNoU2l6ZTogMjAsXG4gICAgICAgICAgeWllbGRUaHJlc2hvbGQ6IDEwLFxuICAgICAgICB9KSxcbiAgICAgICdncm91cEJ5SW5CYXRjaGVzIHsgYmF0Y2hTaXplOiAyMCwgeWllbGRUaHJlc2hvbGQ6IDEwIH0nLFxuICAgICk7XG4gICAgYXdhaXQgYmVuY2goXG4gICAgICAoKSA9PlxuICAgICAgICBncm91cEJ5SW5CYXRjaGVzKGFyciwgKHgpID0+ICh4ICUgMiA9PT0gMCA/ICdldmVuJyA6ICdvZGQnKSwge1xuICAgICAgICAgIGJhdGNoU2l6ZTogMjAsXG4gICAgICAgICAgeWllbGRUaHJlc2hvbGQ6IDEwLFxuICAgICAgICAgIHNlcXVlbnRpYWxQcm9jZXNzaW5nOiBmYWxzZSxcbiAgICAgICAgfSksXG4gICAgICAnZ3JvdXBCeUluQmF0Y2hlcyB7IGJhdGNoU2l6ZTogMjAsIHlpZWxkVGhyZXNob2xkOiAxMCwgc2VxdWVudGlhbFByb2Nlc3Npbmc6IGZhbHNlIH0nLFxuICAgICk7XG4gICAgYXdhaXQgYmVuY2goXG4gICAgICAoKSA9PiBQcm9taXNlLnJlc29sdmUobG9kYXNoLmdyb3VwQnkoYXJyLCAoeCkgPT4gKHggJSAyID09PSAwID8gJ2V2ZW4nIDogJ29kZCcpKSksXG4gICAgICAnbG9kYXNoLmdyb3VwQnknLFxuICAgICk7XG4gIH0pO1xuXG4gIGF3YWl0IHNlY3Rpb24oJ3JlZHVjZScsIGFzeW5jICgpID0+IHtcbiAgICBhd2FpdCBiZW5jaChcbiAgICAgICgpID0+IHJlZHVjZUluQmF0Y2hlcyhhcnIsIChhY2MsIHgpID0+IGFjYyArIHgsIDAsIHsgYmF0Y2hTaXplOiAyMCwgeWllbGRUaHJlc2hvbGQ6IDEwIH0pLFxuICAgICAgJ3JlZHVjZUluQmF0Y2hlcyB7IGJhdGNoU2l6ZTogMjAsIHlpZWxkVGhyZXNob2xkOiAxMCB9JyxcbiAgICApO1xuICAgIGF3YWl0IGJlbmNoKCgpID0+IFByb21pc2UucmVzb2x2ZShsb2Rhc2gucmVkdWNlKGFyciwgKGFjYywgeCkgPT4gYWNjICsgeCwgMCkpLCAnbG9kYXNoLnJlZHVjZScpO1xuICAgIGF3YWl0IGJlbmNoKFxuICAgICAgKCkgPT4gUHJvbWlzZS5yZXNvbHZlKGFyci5yZWR1Y2UoKGFjYywgeCkgPT4gYWNjICsgeCwgMCkpLFxuICAgICAgJ0FycmF5LnByb3RvdHlwZS5yZWR1Y2UnLFxuICAgICk7XG4gIH0pO1xuXG4gIGF3YWl0IHNlY3Rpb24oJ2ZsYXRNYXAnLCBhc3luYyAoKSA9PiB7XG4gICAgYXdhaXQgYmVuY2goXG4gICAgICAoKSA9PiBmbGF0TWFwSW5CYXRjaGVzKGFyciwgKHgpID0+IFt4LCB4XSwgeyBiYXRjaFNpemU6IDIwLCB5aWVsZFRocmVzaG9sZDogMTAgfSksXG4gICAgICAnZmxhdE1hcEluQmF0Y2hlcyB7IGJhdGNoU2l6ZTogMjAsIHlpZWxkVGhyZXNob2xkOiAxMCB9JyxcbiAgICApO1xuICAgIGF3YWl0IGJlbmNoKFxuICAgICAgKCkgPT5cbiAgICAgICAgZmxhdE1hcEluQmF0Y2hlcyhhcnIsICh4KSA9PiBbeCwgeF0sIHtcbiAgICAgICAgICBiYXRjaFNpemU6IDIwLFxuICAgICAgICAgIHlpZWxkVGhyZXNob2xkOiAxMCxcbiAgICAgICAgICBzZXF1ZW50aWFsUHJvY2Vzc2luZzogZmFsc2UsXG4gICAgICAgIH0pLFxuICAgICAgJ2ZsYXRNYXBJbkJhdGNoZXMgeyBiYXRjaFNpemU6IDIwLCB5aWVsZFRocmVzaG9sZDogMTAsIHNlcXVlbnRpYWxQcm9jZXNzaW5nOiBmYWxzZSB9JyxcbiAgICApO1xuICAgIGF3YWl0IGJlbmNoKCgpID0+IFByb21pc2UucmVzb2x2ZShsb2Rhc2guZmxhdE1hcChhcnIsICh4KSA9PiBbeCwgeF0pKSwgJ2xvZGFzaC5mbGF0TWFwJyk7XG4gICAgYXdhaXQgYmVuY2goXG4gICAgICAoKSA9PlxuICAgICAgICBQcm9taXNlLnJlc29sdmUoXG4gICAgICAgICAgYXJyLmZsYXRNYXBcbiAgICAgICAgICAgID8gYXJyLmZsYXRNYXAoKHgpID0+IFt4LCB4XSlcbiAgICAgICAgICAgIDogKFtdIGFzIG51bWJlcltdKS5jb25jYXQoLi4uYXJyLm1hcCgoeCkgPT4gW3gsIHhdKSksXG4gICAgICAgICksXG4gICAgICAnQXJyYXkucHJvdG90eXBlLmZsYXRNYXAnLFxuICAgICk7XG4gIH0pO1xuXG4gIGF3YWl0IHNlY3Rpb24oJ2ZvckVhY2gnLCBhc3luYyAoKSA9PiB7XG4gICAgYXdhaXQgYmVuY2goXG4gICAgICAoKSA9PiBmb3JFYWNoSW5CYXRjaGVzKGFyciwgKCkgPT4ge30sIHsgYmF0Y2hTaXplOiAyMCwgeWllbGRUaHJlc2hvbGQ6IDEwIH0pLFxuICAgICAgJ2ZvckVhY2hJbkJhdGNoZXMgeyBiYXRjaFNpemU6IDIwLCB5aWVsZFRocmVzaG9sZDogMTAgfScsXG4gICAgKTtcbiAgICBhd2FpdCBiZW5jaChcbiAgICAgICgpID0+XG4gICAgICAgIGZvckVhY2hJbkJhdGNoZXMoYXJyLCAoKSA9PiB7fSwge1xuICAgICAgICAgIGJhdGNoU2l6ZTogMjAsXG4gICAgICAgICAgeWllbGRUaHJlc2hvbGQ6IDEwLFxuICAgICAgICAgIHNlcXVlbnRpYWxQcm9jZXNzaW5nOiBmYWxzZSxcbiAgICAgICAgfSksXG4gICAgICAnZm9yRWFjaEluQmF0Y2hlcyB7IGJhdGNoU2l6ZTogMjAsIHlpZWxkVGhyZXNob2xkOiAxMCwgc2VxdWVudGlhbFByb2Nlc3Npbmc6IGZhbHNlIH0nLFxuICAgICk7XG4gICAgYXdhaXQgYmVuY2goKCkgPT4gUHJvbWlzZS5yZXNvbHZlKGFyci5mb3JFYWNoKCgpID0+IHt9KSksICdBcnJheS5wcm90b3R5cGUuZm9yRWFjaCcpO1xuICAgIGF3YWl0IGJlbmNoKCgpID0+IFByb21pc2UucmVzb2x2ZShsb2Rhc2guZm9yRWFjaChhcnIsICgpID0+IHt9KSksICdsb2Rhc2guZm9yRWFjaCcpO1xuICB9KTtcbn1cblxuLy8gdG8gcnVuIGJlbmNobWFya3MgdXNlOiBucHggdHMtbm9kZSBzcmMvdXRpbHMvYmF0Y2gtcHJvY2Vzc2luZy5iZW5jaC50c1xuaWYgKHJlcXVpcmUubWFpbiA9PT0gbW9kdWxlKSB7XG4gIHJ1bkJlbmNobWFya3MoKS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgfSk7XG59XG4iXX0=
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Options for batch processing operations
|
|
3
3
|
*/
|
|
4
|
-
export interface
|
|
4
|
+
export interface BatchProcessingOptions {
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Number of items to process in each batch (default: 10)
|
|
7
|
+
* Must be a positive integer.
|
|
7
8
|
*/
|
|
8
9
|
batchSize?: number;
|
|
9
10
|
/**
|
|
10
|
-
*
|
|
11
|
+
* Time threshold in milliseconds (default: 10) before yielding control back to the event loop.
|
|
12
|
+
* Set to 0 to yield after every batch. Must be a non-negative integer.
|
|
11
13
|
*/
|
|
12
14
|
yieldThreshold?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Whether to process items sequentially within each batch. When true (default), each item in a batch
|
|
17
|
+
* will be processed one at a time. When false, all items in a batch will be processed concurrently.
|
|
18
|
+
* Consider the implications of concurrency on your processing logic before setting this to false, e.g. race conditions, rate limits, memory pressure, etc.
|
|
19
|
+
*/
|
|
20
|
+
sequentialProcessing?: boolean;
|
|
13
21
|
}
|
|
14
22
|
/**
|
|
15
23
|
* Configure global defaults for batch processing operations
|
|
@@ -25,11 +33,14 @@ export interface BatchProcessingDefaults {
|
|
|
25
33
|
* // Set only batch size
|
|
26
34
|
* configureBatchProcessingDefaults({ batchSize: 50 });
|
|
27
35
|
*
|
|
36
|
+
* // Enable concurrent processing within batches
|
|
37
|
+
* configureBatchProcessingDefaults({ sequentialProcessing: false });
|
|
38
|
+
*
|
|
28
39
|
* // Get current configuration
|
|
29
40
|
* const currentConfig = configureBatchProcessingDefaults();
|
|
30
41
|
* ```
|
|
31
42
|
*/
|
|
32
|
-
export declare function configureBatchProcessingDefaults(config?:
|
|
43
|
+
export declare function configureBatchProcessingDefaults(config?: BatchProcessingOptions): BatchProcessingOptions;
|
|
33
44
|
/**
|
|
34
45
|
* Maps over an array in batches to avoid blocking the event loop.
|
|
35
46
|
* Processes items in chunks and yields control back to the event loop between batches
|
|
@@ -39,26 +50,20 @@ export declare function configureBatchProcessingDefaults(config?: BatchProcessin
|
|
|
39
50
|
* @template R - The type of items in the result array
|
|
40
51
|
* @param items - The array to map over
|
|
41
52
|
* @param mapFn - The mapping function to apply to each item. Receives the item and its index.
|
|
42
|
-
* @param
|
|
43
|
-
* @param yieldThreshold - Time threshold in milliseconds before yielding control (default: @see defaultYieldThreshold)
|
|
53
|
+
* @param options - Batch processing options
|
|
44
54
|
* @returns A promise that resolves to the mapped array
|
|
45
55
|
* @throws {Error} When batchSize is not a positive integer
|
|
46
56
|
*
|
|
47
57
|
* @example
|
|
48
58
|
* ```typescript
|
|
49
|
-
* // Synchronous mapping
|
|
50
|
-
* const doubled = await mapInBatches([1, 2, 3, 4], (x) => x * 2
|
|
51
|
-
* // Result: [2, 4, 6, 8]
|
|
52
|
-
*
|
|
53
|
-
* // Asynchronous mapping
|
|
54
|
-
* const fetched = await mapInBatches(urls, async (url) => fetch(url), 3);
|
|
59
|
+
* // Synchronous mapping with default options (sequential processing)
|
|
60
|
+
* const doubled = await mapInBatches([1, 2, 3, 4], (x) => x * 2);
|
|
55
61
|
*
|
|
56
|
-
* // With
|
|
57
|
-
* const
|
|
58
|
-
* // Result: ['a-0', 'b-1']
|
|
62
|
+
* // With concurrent processing within batches
|
|
63
|
+
* const doubled = await mapInBatches([1, 2, 3, 4], (x) => x * 2, { sequentialProcessing: false });
|
|
59
64
|
* ```
|
|
60
65
|
*/
|
|
61
|
-
export declare function mapInBatches<T, R>(items: T[], mapFn: (item: T, index: number) => R | Promise<R>,
|
|
66
|
+
export declare function mapInBatches<T, R>(items: T[], mapFn: (item: T, index: number) => R | Promise<R>, options?: BatchProcessingOptions): Promise<R[]>;
|
|
62
67
|
/**
|
|
63
68
|
* Filters an array in batches to avoid blocking the event loop.
|
|
64
69
|
* Processes items in chunks and yields control back to the event loop between batches
|
|
@@ -67,29 +72,21 @@ export declare function mapInBatches<T, R>(items: T[], mapFn: (item: T, index: n
|
|
|
67
72
|
* @template T - The type of items in the array
|
|
68
73
|
* @param items - The array to filter
|
|
69
74
|
* @param predicate - The predicate function to test each item. Receives the item and its index.
|
|
70
|
-
* @param
|
|
71
|
-
* @param yieldThreshold - Time threshold in milliseconds before yielding control (default: @see defaultYieldThreshold)
|
|
75
|
+
* @param options - Batch processing options
|
|
72
76
|
* @returns A promise that resolves to the filtered array
|
|
73
77
|
* @throws {Error} When batchSize is not a positive integer
|
|
74
78
|
*
|
|
75
79
|
* @example
|
|
76
80
|
* ```typescript
|
|
77
|
-
* // Synchronous filtering
|
|
78
|
-
* const evens = await filterInBatches([1, 2, 3, 4, 5], (x) => x % 2 === 0
|
|
81
|
+
* // Synchronous filtering with default options
|
|
82
|
+
* const evens = await filterInBatches([1, 2, 3, 4, 5], (x) => x % 2 === 0);
|
|
79
83
|
* // Result: [2, 4]
|
|
80
84
|
*
|
|
81
|
-
* //
|
|
82
|
-
* const
|
|
83
|
-
* const response = await fetch(url);
|
|
84
|
-
* return response.ok;
|
|
85
|
-
* }, 3);
|
|
86
|
-
*
|
|
87
|
-
* // With index
|
|
88
|
-
* const evenIndices = await filterInBatches(['a', 'b', 'c'], (_, index) => index % 2 === 0);
|
|
89
|
-
* // Result: ['a', 'c']
|
|
85
|
+
* // With custom batch size
|
|
86
|
+
* const evens = await filterInBatches([1, 2, 3, 4, 5], (x) => x % 2 === 0, { batchSize: 2 });
|
|
90
87
|
* ```
|
|
91
88
|
*/
|
|
92
|
-
export declare function filterInBatches<T>(items: T[], predicate: (item: T, index: number) => boolean | Promise<boolean>,
|
|
89
|
+
export declare function filterInBatches<T>(items: T[], predicate: (item: T, index: number) => boolean | Promise<boolean>, options?: BatchProcessingOptions): Promise<T[]>;
|
|
93
90
|
/**
|
|
94
91
|
* Groups an array by a key function in batches to avoid blocking the event loop.
|
|
95
92
|
* Processes items in chunks and yields control back to the event loop between batches
|
|
@@ -99,73 +96,54 @@ export declare function filterInBatches<T>(items: T[], predicate: (item: T, inde
|
|
|
99
96
|
* @template K - The type of the grouping key (must extend PropertyKey)
|
|
100
97
|
* @param items - The array to group
|
|
101
98
|
* @param keyFn - The function to extract the grouping key from each item. Receives the item and its index.
|
|
102
|
-
* @param
|
|
103
|
-
* @param yieldThreshold - Time threshold in milliseconds before yielding control (default: @see defaultYieldThreshold)
|
|
99
|
+
* @param options - Batch processing options
|
|
104
100
|
* @returns A promise that resolves to an object with grouped items
|
|
105
101
|
* @throws {Error} When batchSize is not a positive integer
|
|
106
102
|
*
|
|
107
103
|
* @example
|
|
108
104
|
* ```typescript
|
|
109
|
-
* // Group by property
|
|
105
|
+
* // Group by property with default options
|
|
110
106
|
* const byType = await groupByInBatches(
|
|
111
107
|
* [{type: 'A', value: 1}, {type: 'B', value: 2}, {type: 'A', value: 3}],
|
|
112
|
-
* (item) => item.type
|
|
113
|
-
* 2
|
|
108
|
+
* (item) => item.type
|
|
114
109
|
* );
|
|
115
110
|
* // Result: {A: [{type: 'A', value: 1}, {type: 'A', value: 3}], B: [{type: 'B', value: 2}]}
|
|
116
111
|
*
|
|
117
|
-
* //
|
|
118
|
-
* const
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* return await getCategoryForItem(item);
|
|
124
|
-
* });
|
|
112
|
+
* // With custom batch size
|
|
113
|
+
* const byType = await groupByInBatches(
|
|
114
|
+
* [{type: 'A', value: 1}, {type: 'B', value: 2}, {type: 'A', value: 3}],
|
|
115
|
+
* (item) => item.type,
|
|
116
|
+
* { batchSize: 2 }
|
|
117
|
+
* );
|
|
125
118
|
* ```
|
|
126
119
|
*/
|
|
127
|
-
export declare function groupByInBatches<T, K extends PropertyKey>(items: T[], keyFn: (item: T, index: number) => K | Promise<K>,
|
|
120
|
+
export declare function groupByInBatches<T, K extends PropertyKey>(items: T[], keyFn: (item: T, index: number) => K | Promise<K>, options?: BatchProcessingOptions): Promise<Record<K, T[]>>;
|
|
128
121
|
/**
|
|
129
122
|
* Reduces an array in batches to avoid blocking the event loop.
|
|
130
123
|
* Processes items in chunks and yields control back to the event loop between batches
|
|
131
|
-
* when the processing time exceeds the threshold.
|
|
124
|
+
* when the processing time exceeds the threshold. Sequential processing is always used for the reducer function,
|
|
125
|
+
* irrespective of the `sequentialProcessing` option.
|
|
132
126
|
*
|
|
133
127
|
* @template T - The type of items in the array
|
|
134
128
|
* @template R - The type of the accumulator/result
|
|
135
129
|
* @param items - The array to reduce
|
|
136
130
|
* @param reducer - The reducer function. Receives the accumulator, current item, and index.
|
|
137
131
|
* @param initialValue - The initial value for the accumulator
|
|
138
|
-
* @param
|
|
139
|
-
* @param yieldThreshold - Time threshold in milliseconds before yielding control (default: @see defaultYieldThreshold)
|
|
132
|
+
* @param options - Batch processing options
|
|
140
133
|
* @returns A promise that resolves to the reduced value
|
|
141
134
|
* @throws {Error} When batchSize is not a positive integer
|
|
142
135
|
*
|
|
143
136
|
* @example
|
|
144
137
|
* ```typescript
|
|
145
|
-
* // Sum numbers
|
|
146
|
-
* const sum = await reduceInBatches([1, 2, 3, 4], (acc, x) => acc + x, 0
|
|
138
|
+
* // Sum numbers with default options
|
|
139
|
+
* const sum = await reduceInBatches([1, 2, 3, 4], (acc, x) => acc + x, 0);
|
|
147
140
|
* // Result: 10
|
|
148
141
|
*
|
|
149
|
-
* //
|
|
150
|
-
* const
|
|
151
|
-
* // Result: 'abc'
|
|
152
|
-
*
|
|
153
|
-
* // Build object with index
|
|
154
|
-
* const indexed = await reduceInBatches(
|
|
155
|
-
* ['x', 'y'],
|
|
156
|
-
* (acc, item, index) => ({ ...acc, [index]: item }),
|
|
157
|
-
* {}
|
|
158
|
-
* );
|
|
159
|
-
* // Result: {0: 'x', 1: 'y'}
|
|
160
|
-
*
|
|
161
|
-
* // Asynchronous reducer
|
|
162
|
-
* const processed = await reduceInBatches(urls, async (acc, url) => {
|
|
163
|
-
* const data = await fetch(url).then(r => r.json());
|
|
164
|
-
* return [...acc, data];
|
|
165
|
-
* }, []);
|
|
142
|
+
* // With custom batch size
|
|
143
|
+
* const sum = await reduceInBatches([1, 2, 3, 4], (acc, x) => acc + x, 0, { batchSize: 2 });
|
|
166
144
|
* ```
|
|
167
145
|
*/
|
|
168
|
-
export declare function reduceInBatches<T, R>(items: T[], reducer: (acc: R, item: T, index: number) => R | Promise<R>, initialValue: R,
|
|
146
|
+
export declare function reduceInBatches<T, R>(items: T[], reducer: (acc: R, item: T, index: number) => R | Promise<R>, initialValue: R, options?: BatchProcessingOptions): Promise<R>;
|
|
169
147
|
/**
|
|
170
148
|
* FlatMaps an array in batches to avoid blocking the event loop.
|
|
171
149
|
* Processes items in chunks, flattens the results, and yields control back to the event loop between batches
|
|
@@ -175,31 +153,45 @@ export declare function reduceInBatches<T, R>(items: T[], reducer: (acc: R, item
|
|
|
175
153
|
* @template R - The type of items in the flattened result array
|
|
176
154
|
* @param items - The array to flatMap over
|
|
177
155
|
* @param mapFn - The mapping function that returns an array for each item. Receives the item and its index.
|
|
178
|
-
* @param
|
|
179
|
-
* @param yieldThreshold - Time threshold in milliseconds before yielding control (default: @see defaultYieldThreshold)
|
|
156
|
+
* @param options - Batch processing options
|
|
180
157
|
* @returns A promise that resolves to the flattened mapped array
|
|
181
158
|
* @throws {Error} When batchSize is not a positive integer
|
|
182
159
|
*
|
|
183
160
|
* @example
|
|
184
161
|
* ```typescript
|
|
185
|
-
* // Duplicate each item
|
|
186
|
-
* const duplicated = await flatMapInBatches([1, 2, 3], (x) => [x, x]
|
|
162
|
+
* // Duplicate each item with default options
|
|
163
|
+
* const duplicated = await flatMapInBatches([1, 2, 3], (x) => [x, x]);
|
|
187
164
|
* // Result: [1, 1, 2, 2, 3, 3]
|
|
188
165
|
*
|
|
189
|
-
* //
|
|
190
|
-
* const
|
|
191
|
-
*
|
|
166
|
+
* // With custom batch size
|
|
167
|
+
* const duplicated = await flatMapInBatches([1, 2, 3], (x) => [x, x], { batchSize: 2 });
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
export declare function flatMapInBatches<T, R>(items: T[], mapFn: (item: T, index: number) => R[] | Promise<R[]>, options?: BatchProcessingOptions): Promise<R[]>;
|
|
171
|
+
/**
|
|
172
|
+
* forEach over an array in batches to avoid blocking the event loop.
|
|
173
|
+
* Processes items in chunks and yields control back to the event loop between batches
|
|
174
|
+
* when the processing time exceeds the threshold.
|
|
192
175
|
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
176
|
+
* @template T - The type of items in the input array
|
|
177
|
+
* @param items - The array to iterate over
|
|
178
|
+
* @param fn - The function to apply to each item. Receives the item and its index. Can be async.
|
|
179
|
+
* @param options - Batch processing options
|
|
180
|
+
* @returns A promise that resolves when all items have been processed
|
|
181
|
+
* @throws {Error} When batchSize is not a positive integer
|
|
196
182
|
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```typescript
|
|
185
|
+
* // Process items in batches with default options
|
|
186
|
+
* await forEachInBatches([1, 2, 3, 4], async (x) => {
|
|
187
|
+
* await doSomething(x);
|
|
201
188
|
* });
|
|
189
|
+
*
|
|
190
|
+
* // With custom batch size
|
|
191
|
+
* await forEachInBatches([1, 2, 3, 4], async (x) => {
|
|
192
|
+
* await doSomething(x);
|
|
193
|
+
* }, { batchSize: 2 });
|
|
202
194
|
* ```
|
|
203
195
|
*/
|
|
204
|
-
export declare function
|
|
196
|
+
export declare function forEachInBatches<T>(items: T[], fn: (item: T, index: number) => void | Promise<void>, options?: BatchProcessingOptions): Promise<void>;
|
|
205
197
|
//# sourceMappingURL=batch-processing.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch-processing.d.ts","sourceRoot":"","sources":["../../src/utils/batch-processing.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"batch-processing.d.ts","sourceRoot":"","sources":["../../src/utils/batch-processing.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAOD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gCAAgC,CAC9C,MAAM,CAAC,EAAE,sBAAsB,GAC9B,sBAAsB,CA0BxB;AAoFD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,CAAC,EAC/B,KAAK,EAAE,CAAC,EAAE,EACV,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EACjD,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,CAAC,EAAE,CAAC,CAqBd;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAC/B,KAAK,EAAE,CAAC,EAAE,EACV,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,EACjE,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,CAAC,EAAE,CAAC,CAuBd;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,CAAC,SAAS,WAAW,EACvD,KAAK,EAAE,CAAC,EAAE,EACV,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EACjD,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CA0BzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,EAClC,KAAK,EAAE,CAAC,EAAE,EACV,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAC3D,YAAY,EAAE,CAAC,EACf,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,CAAC,CAAC,CAcZ;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,CAAC,EACnC,KAAK,EAAE,CAAC,EAAE,EACV,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,EACrD,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,CAAC,EAAE,CAAC,CAuBd;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,KAAK,EAAE,CAAC,EAAE,EACV,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EACpD,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAef"}
|
|
@@ -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=
|