@appium/support 2.61.1 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/build/lib/console.d.ts +1 -1
  2. package/build/lib/console.js +169 -105
  3. package/build/lib/console.js.map +1 -1
  4. package/build/lib/env.d.ts.map +1 -1
  5. package/build/lib/env.js +144 -117
  6. package/build/lib/env.js.map +1 -1
  7. package/build/lib/fs.d.ts +9 -2
  8. package/build/lib/fs.d.ts.map +1 -1
  9. package/build/lib/fs.js +358 -246
  10. package/build/lib/fs.js.map +1 -1
  11. package/build/lib/image-util.js +139 -124
  12. package/build/lib/image-util.js.map +1 -1
  13. package/build/lib/index.js +64 -103
  14. package/build/lib/index.js.map +1 -1
  15. package/build/lib/log-internal.d.ts +4 -27
  16. package/build/lib/log-internal.d.ts.map +1 -1
  17. package/build/lib/log-internal.js +141 -123
  18. package/build/lib/log-internal.js.map +1 -1
  19. package/build/lib/logger.d.ts +1 -1
  20. package/build/lib/logger.d.ts.map +1 -1
  21. package/build/lib/logger.js +5 -14
  22. package/build/lib/logger.js.map +1 -1
  23. package/build/lib/logging.d.ts +3 -4
  24. package/build/lib/logging.d.ts.map +1 -1
  25. package/build/lib/logging.js +139 -110
  26. package/build/lib/logging.js.map +1 -1
  27. package/build/lib/mjpeg.js +169 -141
  28. package/build/lib/mjpeg.js.map +1 -1
  29. package/build/lib/mkdirp.js +7 -13
  30. package/build/lib/mkdirp.js.map +1 -1
  31. package/build/lib/net.d.ts.map +1 -1
  32. package/build/lib/net.js +278 -254
  33. package/build/lib/net.js.map +1 -1
  34. package/build/lib/node.js +203 -192
  35. package/build/lib/node.js.map +1 -1
  36. package/build/lib/npm.d.ts +19 -4
  37. package/build/lib/npm.d.ts.map +1 -1
  38. package/build/lib/npm.js +277 -228
  39. package/build/lib/npm.js.map +1 -1
  40. package/build/lib/plist.js +145 -136
  41. package/build/lib/plist.js.map +1 -1
  42. package/build/lib/process.js +41 -42
  43. package/build/lib/process.js.map +1 -1
  44. package/build/lib/system.js +39 -56
  45. package/build/lib/system.js.map +1 -1
  46. package/build/lib/tempdir.js +112 -73
  47. package/build/lib/tempdir.js.map +1 -1
  48. package/build/lib/timing.js +99 -84
  49. package/build/lib/timing.js.map +1 -1
  50. package/build/lib/util.js +454 -356
  51. package/build/lib/util.js.map +1 -1
  52. package/build/lib/zip.js +469 -423
  53. package/build/lib/zip.js.map +1 -1
  54. package/build/tsconfig.tsbuildinfo +1 -1
  55. package/lib/env.js +6 -4
  56. package/lib/fs.js +15 -1
  57. package/lib/log-internal.js +12 -16
  58. package/lib/logging.js +2 -3
  59. package/lib/net.js +15 -6
  60. package/lib/npm.js +28 -18
  61. package/package.json +20 -19
package/build/lib/zip.js CHANGED
@@ -1,461 +1,507 @@
1
1
  "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports._extractEntryTo = _extractEntryTo;
7
- exports.assertValidZip = assertValidZip;
8
- exports.default = void 0;
9
- exports.extractAllTo = extractAllTo;
10
- exports.readEntries = readEntries;
11
- exports.toArchive = toArchive;
12
- exports.toInMemoryZip = toInMemoryZip;
13
-
14
- require("source-map-support/register");
15
-
16
- var _lodash = _interopRequireDefault(require("lodash"));
17
-
18
- var _bluebird = _interopRequireDefault(require("bluebird"));
19
-
20
- var _yauzl = _interopRequireDefault(require("yauzl"));
21
-
22
- var _archiver = _interopRequireDefault(require("archiver"));
23
-
24
- var _fs = require("fs");
25
-
26
- var _path = _interopRequireDefault(require("path"));
27
-
28
- var _stream = _interopRequireDefault(require("stream"));
29
-
30
- var _fs2 = _interopRequireDefault(require("./fs"));
31
-
32
- var _system = require("./system");
33
-
34
- var _base64Stream = require("base64-stream");
35
-
36
- var _util = require("./util");
37
-
38
- var _timing = _interopRequireDefault(require("./timing"));
39
-
40
- var _logger = _interopRequireDefault(require("./logger"));
41
-
42
- var _getStream = _interopRequireDefault(require("get-stream"));
43
-
44
- var _teen_process = require("teen_process");
45
-
46
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
47
-
48
- const openZip = _bluebird.default.promisify(_yauzl.default.open);
49
-
50
- const pipeline = _bluebird.default.promisify(_stream.default.pipeline);
51
-
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
+ exports.toArchive = exports.assertValidZip = exports._extractEntryTo = exports.toInMemoryZip = exports.readEntries = exports.extractAllTo = void 0;
7
+ const lodash_1 = __importDefault(require("lodash"));
8
+ const bluebird_1 = __importDefault(require("bluebird"));
9
+ const yauzl_1 = __importDefault(require("yauzl"));
10
+ const archiver_1 = __importDefault(require("archiver"));
11
+ const fs_1 = require("fs");
12
+ const path_1 = __importDefault(require("path"));
13
+ const stream_1 = __importDefault(require("stream"));
14
+ const fs_2 = __importDefault(require("./fs"));
15
+ const system_1 = require("./system");
16
+ const base64_stream_1 = require("base64-stream");
17
+ const util_1 = require("./util");
18
+ const timing_1 = __importDefault(require("./timing"));
19
+ const logger_1 = __importDefault(require("./logger"));
20
+ const get_stream_1 = __importDefault(require("get-stream"));
21
+ const teen_process_1 = require("teen_process");
22
+ /**
23
+ * @type {(path: string, options?: yauzl.Options) => Promise<yauzl.ZipFile>}
24
+ */
25
+ const openZip = bluebird_1.default.promisify(yauzl_1.default.open);
26
+ /**
27
+ * @type {(source: NodeJS.ReadableStream, destination: NodeJS.WritableStream) => Promise<NodeJS.WritableStream>}
28
+ */
29
+ const pipeline = bluebird_1.default.promisify(stream_1.default.pipeline);
52
30
  const ZIP_MAGIC = 'PK';
53
31
  const IFMT = 61440;
54
32
  const IFDIR = 16384;
55
33
  const IFLNK = 40960;
56
-
34
+ // This class is mostly copied from https://github.com/maxogden/extract-zip/blob/master/index.js
57
35
  class ZipExtractor {
58
- zipfile;
59
-
60
- constructor(sourcePath, opts = {}) {
61
- this.zipPath = sourcePath;
62
- this.opts = opts;
63
- this.canceled = false;
64
- }
65
-
66
- extractFileName(entry) {
67
- return _lodash.default.isBuffer(entry.fileName) ? entry.fileName.toString(this.opts.fileNamesEncoding) : entry.fileName;
68
- }
69
-
70
- async extract() {
71
- const {
72
- dir,
73
- fileNamesEncoding
74
- } = this.opts;
75
- this.zipfile = await openZip(this.zipPath, {
76
- lazyEntries: true,
77
- decodeStrings: !fileNamesEncoding
78
- });
79
- this.canceled = false;
80
- return new _bluebird.default((resolve, reject) => {
81
- this.zipfile.on('error', err => {
82
- this.canceled = true;
83
- reject(err);
84
- });
85
- this.zipfile.readEntry();
86
- this.zipfile.on('close', () => {
87
- if (!this.canceled) {
88
- resolve();
89
- }
90
- });
91
- this.zipfile.on('entry', async entry => {
36
+ constructor(sourcePath, opts = {}) {
37
+ this.zipPath = sourcePath;
38
+ this.opts = opts;
39
+ this.canceled = false;
40
+ }
41
+ extractFileName(entry) {
42
+ return lodash_1.default.isBuffer(entry.fileName)
43
+ ? entry.fileName.toString(this.opts.fileNamesEncoding)
44
+ : entry.fileName;
45
+ }
46
+ async extract() {
47
+ const { dir, fileNamesEncoding } = this.opts;
48
+ this.zipfile = await openZip(this.zipPath, {
49
+ lazyEntries: true,
50
+ // https://github.com/thejoshwolfe/yauzl/commit/cc7455ac789ba84973184e5ebde0581cdc4c3b39#diff-04c6e90faac2675aa89e2176d2eec7d8R95
51
+ decodeStrings: !fileNamesEncoding,
52
+ });
53
+ this.canceled = false;
54
+ return new bluebird_1.default((resolve, reject) => {
55
+ this.zipfile.on('error', (err) => {
56
+ this.canceled = true;
57
+ reject(err);
58
+ });
59
+ this.zipfile.readEntry();
60
+ this.zipfile.on('close', () => {
61
+ if (!this.canceled) {
62
+ resolve();
63
+ }
64
+ });
65
+ this.zipfile.on('entry', async (entry) => {
66
+ if (this.canceled) {
67
+ return;
68
+ }
69
+ const fileName = this.extractFileName(entry);
70
+ if (fileName.startsWith('__MACOSX/')) {
71
+ this.zipfile.readEntry();
72
+ return;
73
+ }
74
+ const destDir = path_1.default.dirname(path_1.default.join(dir, fileName));
75
+ try {
76
+ await fs_2.default.mkdir(destDir, { recursive: true });
77
+ const canonicalDestDir = await fs_2.default.realpath(destDir);
78
+ const relativeDestDir = path_1.default.relative(dir, canonicalDestDir);
79
+ if (relativeDestDir.split(path_1.default.sep).includes('..')) {
80
+ new Error(`Out of bound path "${canonicalDestDir}" found while processing file ${fileName}`);
81
+ }
82
+ await this.extractEntry(entry);
83
+ this.zipfile.readEntry();
84
+ }
85
+ catch (err) {
86
+ this.canceled = true;
87
+ this.zipfile.close();
88
+ reject(err);
89
+ }
90
+ });
91
+ });
92
+ }
93
+ async extractEntry(entry) {
92
94
  if (this.canceled) {
93
- return;
95
+ return;
94
96
  }
95
-
97
+ const { dir } = this.opts;
96
98
  const fileName = this.extractFileName(entry);
97
-
98
- if (fileName.startsWith('__MACOSX/')) {
99
- this.zipfile.readEntry();
100
- return;
99
+ const dest = path_1.default.join(dir, fileName);
100
+ // convert external file attr int into a fs stat mode int
101
+ const mode = (entry.externalFileAttributes >> 16) & 0xffff;
102
+ // check if it's a symlink or dir (using stat mode constants)
103
+ const isSymlink = (mode & IFMT) === IFLNK;
104
+ const isDir = (mode & IFMT) === IFDIR ||
105
+ // Failsafe, borrowed from jsZip
106
+ fileName.endsWith('/') ||
107
+ // check for windows weird way of specifying a directory
108
+ // https://github.com/maxogden/extract-zip/issues/13#issuecomment-154494566
109
+ (entry.versionMadeBy >> 8 === 0 && entry.externalFileAttributes === 16);
110
+ const procMode = this.getExtractedMode(mode, isDir) & 0o777;
111
+ // always ensure folders are created
112
+ const destDir = isDir ? dest : path_1.default.dirname(dest);
113
+ const mkdirOptions = { recursive: true };
114
+ if (isDir) {
115
+ mkdirOptions.mode = procMode;
101
116
  }
102
-
103
- const destDir = _path.default.dirname(_path.default.join(dir, fileName));
104
-
105
- try {
106
- await _fs2.default.mkdir(destDir, {
107
- recursive: true
108
- });
109
- const canonicalDestDir = await _fs2.default.realpath(destDir);
110
-
111
- const relativeDestDir = _path.default.relative(dir, canonicalDestDir);
112
-
113
- if (relativeDestDir.split(_path.default.sep).includes('..')) {
114
- new Error(`Out of bound path "${canonicalDestDir}" found while processing file ${fileName}`);
115
- }
116
-
117
- await this.extractEntry(entry);
118
- this.zipfile.readEntry();
119
- } catch (err) {
120
- this.canceled = true;
121
- this.zipfile.close();
122
- reject(err);
117
+ await fs_2.default.mkdir(destDir, mkdirOptions);
118
+ if (isDir) {
119
+ return;
120
+ }
121
+ /** @type {(entry: yauzl.Entry) => Promise<NodeJS.ReadableStream>} */
122
+ const openReadStream = bluebird_1.default.promisify(this.zipfile.openReadStream.bind(this.zipfile));
123
+ const readStream = await openReadStream(entry);
124
+ if (isSymlink) {
125
+ const link = await (0, get_stream_1.default)(readStream);
126
+ await fs_2.default.symlink(link, dest);
127
+ }
128
+ else {
129
+ await pipeline(readStream, fs_2.default.createWriteStream(dest, { mode: procMode }));
123
130
  }
124
- });
125
- });
126
- }
127
-
128
- async extractEntry(entry) {
129
- if (this.canceled) {
130
- return;
131
- }
132
-
133
- const {
134
- dir
135
- } = this.opts;
136
- const fileName = this.extractFileName(entry);
137
-
138
- const dest = _path.default.join(dir, fileName);
139
-
140
- const mode = entry.externalFileAttributes >> 16 & 0xffff;
141
- const isSymlink = (mode & IFMT) === IFLNK;
142
- const isDir = (mode & IFMT) === IFDIR || fileName.endsWith('/') || entry.versionMadeBy >> 8 === 0 && entry.externalFileAttributes === 16;
143
- const procMode = this.getExtractedMode(mode, isDir) & 0o777;
144
- const destDir = isDir ? dest : _path.default.dirname(dest);
145
- const mkdirOptions = {
146
- recursive: true
147
- };
148
-
149
- if (isDir) {
150
- mkdirOptions.mode = procMode;
151
131
  }
152
-
153
- await _fs2.default.mkdir(destDir, mkdirOptions);
154
-
155
- if (isDir) {
156
- return;
132
+ getExtractedMode(entryMode, isDir) {
133
+ const { defaultDirMode, defaultFileMode } = this.opts;
134
+ let mode = entryMode;
135
+ // Set defaults, if necessary
136
+ if (mode === 0) {
137
+ if (isDir) {
138
+ if (defaultDirMode) {
139
+ mode = parseInt(defaultDirMode, 10);
140
+ }
141
+ if (!mode) {
142
+ mode = 0o755;
143
+ }
144
+ }
145
+ else {
146
+ if (defaultFileMode) {
147
+ mode = parseInt(defaultFileMode, 10);
148
+ }
149
+ if (!mode) {
150
+ mode = 0o644;
151
+ }
152
+ }
153
+ }
154
+ return mode;
157
155
  }
158
-
159
- const openReadStream = _bluebird.default.promisify(this.zipfile.openReadStream.bind(this.zipfile));
160
-
161
- const readStream = await openReadStream(entry);
162
-
163
- if (isSymlink) {
164
- const link = await (0, _getStream.default)(readStream);
165
- await _fs2.default.symlink(link, dest);
166
- } else {
167
- await pipeline(readStream, _fs2.default.createWriteStream(dest, {
168
- mode: procMode
169
- }));
156
+ }
157
+ /**
158
+ * @typedef ExtractAllOptions
159
+ * @property {string} [fileNamesEncoding] The encoding to use for extracted file names.
160
+ * For ZIP archives created on MacOS it is usually expected to be `utf8`.
161
+ * By default it is autodetected based on the entry metadata and is only needed to be set explicitly
162
+ * if the particular archive does not comply to the standards, which leads to corrupted file names
163
+ * after extraction. Only applicable if system unzip binary is NOT being used.
164
+ * @property {boolean} [useSystemUnzip] If true, attempt to use system unzip; if this fails,
165
+ * fallback to the JS unzip implementation.
166
+ */
167
+ /**
168
+ * Extract zipfile to a directory
169
+ *
170
+ * @param {string} zipFilePath The full path to the source ZIP file
171
+ * @param {string} destDir The full path to the destination folder
172
+ * @param {ExtractAllOptions} [opts]
173
+ */
174
+ async function extractAllTo(zipFilePath, destDir, opts = /** @type {ExtractAllOptions} */ ({})) {
175
+ if (!path_1.default.isAbsolute(destDir)) {
176
+ throw new Error(`Target path '${destDir}' is expected to be absolute`);
170
177
  }
171
- }
172
-
173
- getExtractedMode(entryMode, isDir) {
174
- const {
175
- defaultDirMode,
176
- defaultFileMode
177
- } = this.opts;
178
- let mode = entryMode;
179
-
180
- if (mode === 0) {
181
- if (isDir) {
182
- if (defaultDirMode) {
183
- mode = parseInt(defaultDirMode, 10);
184
- }
185
-
186
- if (!mode) {
187
- mode = 0o755;
188
- }
189
- } else {
190
- if (defaultFileMode) {
191
- mode = parseInt(defaultFileMode, 10);
178
+ await fs_2.default.mkdir(destDir, { recursive: true });
179
+ const dir = await fs_2.default.realpath(destDir);
180
+ if (opts.useSystemUnzip) {
181
+ try {
182
+ await extractWithSystemUnzip(zipFilePath, dir);
183
+ return;
192
184
  }
193
-
194
- if (!mode) {
195
- mode = 0o644;
185
+ catch (err) {
186
+ logger_1.default.warn('unzip failed; falling back to JS: %s', err.stderr || err.message);
196
187
  }
197
- }
198
188
  }
199
-
200
- return mode;
201
- }
202
-
189
+ const extractor = new ZipExtractor(zipFilePath, {
190
+ ...opts,
191
+ dir,
192
+ });
193
+ await extractor.extract();
203
194
  }
204
-
205
- async function extractAllTo(zipFilePath, destDir, opts = {}) {
206
- if (!_path.default.isAbsolute(destDir)) {
207
- throw new Error(`Target path '${destDir}' is expected to be absolute`);
208
- }
209
-
210
- await _fs2.default.mkdir(destDir, {
211
- recursive: true
212
- });
213
- const dir = await _fs2.default.realpath(destDir);
214
-
215
- if (opts.useSystemUnzip) {
195
+ exports.extractAllTo = extractAllTo;
196
+ /**
197
+ * Executes system unzip (e.g., `/usr/bin/unzip`). If available, it is
198
+ * significantly faster than the JS implementation.
199
+ * By default all files in the destDir get overridden if already exist.
200
+ *
201
+ * @param {string} zipFilePath The full path to the source ZIP file
202
+ * @param {string} destDir The full path to the destination folder.
203
+ * This folder is expected to already exist before extracting the archive.
204
+ */
205
+ async function extractWithSystemUnzip(zipFilePath, destDir) {
206
+ const isWindowsHost = (0, system_1.isWindows)();
207
+ let executablePath;
216
208
  try {
217
- await extractWithSystemUnzip(zipFilePath, dir);
218
- return;
219
- } catch (err) {
220
- _logger.default.warn('unzip failed; falling back to JS: %s', err.stderr || err.message);
209
+ executablePath = await getExecutablePath(isWindowsHost ? 'powershell.exe' : 'unzip');
210
+ }
211
+ catch (e) {
212
+ throw new Error('Could not find system unzip');
213
+ }
214
+ if (isWindowsHost) {
215
+ // on Windows we use PowerShell to unzip files
216
+ await (0, teen_process_1.exec)(executablePath, [
217
+ '-command',
218
+ 'Expand-Archive',
219
+ '-LiteralPath',
220
+ zipFilePath,
221
+ '-DestinationPath',
222
+ destDir,
223
+ '-Force',
224
+ ]);
225
+ }
226
+ else {
227
+ // -q means quiet (no stdout)
228
+ // -o means overwrite
229
+ // -d is the dest dir
230
+ await (0, teen_process_1.exec)(executablePath, ['-q', '-o', zipFilePath, '-d', destDir]);
221
231
  }
222
- }
223
-
224
- const extractor = new ZipExtractor(zipFilePath, { ...opts,
225
- dir
226
- });
227
- await extractor.extract();
228
- }
229
-
230
- async function extractWithSystemUnzip(zipFilePath, destDir) {
231
- const isWindowsHost = (0, _system.isWindows)();
232
- let executablePath;
233
-
234
- try {
235
- executablePath = await getExecutablePath(isWindowsHost ? 'powershell.exe' : 'unzip');
236
- } catch (e) {
237
- throw new Error('Could not find system unzip');
238
- }
239
-
240
- if (isWindowsHost) {
241
- await (0, _teen_process.exec)(executablePath, ['-command', 'Expand-Archive', '-LiteralPath', zipFilePath, '-DestinationPath', destDir, '-Force']);
242
- } else {
243
- await (0, _teen_process.exec)(executablePath, ['-q', '-o', zipFilePath, '-d', destDir]);
244
- }
245
232
  }
246
-
233
+ /**
234
+ * Extract a single zip entry to a directory
235
+ *
236
+ * @param {yauzl.ZipFile} zipFile The source ZIP stream
237
+ * @param {yauzl.Entry} entry The entry instance
238
+ * @param {string} destDir The full path to the destination folder
239
+ */
247
240
  async function _extractEntryTo(zipFile, entry, destDir) {
248
- const dstPath = _path.default.resolve(destDir, entry.fileName);
249
-
250
- if (/\/$/.test(entry.fileName)) {
251
- if (!(await _fs2.default.exists(dstPath))) {
252
- await _fs2.default.mkdirp(dstPath);
241
+ const dstPath = path_1.default.resolve(destDir, entry.fileName);
242
+ // Create dest directory if doesn't exist already
243
+ if (/\/$/.test(entry.fileName)) {
244
+ if (!(await fs_2.default.exists(dstPath))) {
245
+ await fs_2.default.mkdirp(dstPath);
246
+ }
247
+ return;
248
+ }
249
+ else if (!(await fs_2.default.exists(path_1.default.dirname(dstPath)))) {
250
+ await fs_2.default.mkdirp(path_1.default.dirname(dstPath));
253
251
  }
254
-
255
- return;
256
- } else if (!(await _fs2.default.exists(_path.default.dirname(dstPath)))) {
257
- await _fs2.default.mkdirp(_path.default.dirname(dstPath));
258
- }
259
-
260
- const writeStream = (0, _fs.createWriteStream)(dstPath, {
261
- flags: 'w'
262
- });
263
- const writeStreamPromise = new _bluebird.default((resolve, reject) => {
264
- writeStream.once('finish', resolve);
265
- writeStream.once('error', reject);
266
- });
267
- const zipReadStream = await new _bluebird.default((resolve, reject) => {
268
- zipFile.openReadStream(entry, (err, readStream) => err ? reject(err) : resolve(readStream));
269
- });
270
- const zipReadStreamPromise = new _bluebird.default((resolve, reject) => {
271
- zipReadStream.once('end', resolve);
272
- zipReadStream.once('error', reject);
273
- });
274
- zipReadStream.pipe(writeStream);
275
- return await _bluebird.default.all([zipReadStreamPromise, writeStreamPromise]);
252
+ // Create a write stream
253
+ const writeStream = (0, fs_1.createWriteStream)(dstPath, { flags: 'w' });
254
+ const writeStreamPromise = new bluebird_1.default((resolve, reject) => {
255
+ writeStream.once('finish', resolve);
256
+ writeStream.once('error', reject);
257
+ });
258
+ // Create zipReadStream and pipe data to the write stream
259
+ // (for some odd reason B.promisify doesn't work on zipfile.openReadStream, it causes an error 'closed')
260
+ const zipReadStream = await new bluebird_1.default((resolve, reject) => {
261
+ zipFile.openReadStream(entry, (err, readStream) => (err ? reject(err) : resolve(readStream)));
262
+ });
263
+ const zipReadStreamPromise = new bluebird_1.default((resolve, reject) => {
264
+ zipReadStream.once('end', resolve);
265
+ zipReadStream.once('error', reject);
266
+ });
267
+ zipReadStream.pipe(writeStream);
268
+ // Wait for the zipReadStream and writeStream to end before returning
269
+ return await bluebird_1.default.all([zipReadStreamPromise, writeStreamPromise]);
276
270
  }
277
-
271
+ exports._extractEntryTo = _extractEntryTo;
272
+ /**
273
+ * @typedef ZipEntry
274
+ * @property {yauzl.Entry} entry The actual entry instance
275
+ * @property {function} extractEntryTo An async function, which accepts one parameter.
276
+ * This parameter contains the destination folder path to which this function is going to extract the entry.
277
+ */
278
+ /**
279
+ * Get entries for a zip folder
280
+ *
281
+ * @param {string} zipFilePath The full path to the source ZIP file
282
+ * @param {function} onEntry Callback when entry is read.
283
+ * The callback is expected to accept one argument of ZipEntry type.
284
+ * The iteration through the source zip file will bi terminated as soon as
285
+ * the result of this function equals to `false`.
286
+ */
278
287
  async function readEntries(zipFilePath, onEntry) {
279
- const zipfile = await openZip(zipFilePath, {
280
- lazyEntries: true
281
- });
282
- const zipReadStreamPromise = new _bluebird.default((resolve, reject) => {
283
- zipfile.once('end', resolve);
284
- zipfile.once('error', reject);
285
- zipfile.on('entry', async entry => {
286
- const res = await onEntry({
287
- entry,
288
- extractEntryTo: async destDir => await _extractEntryTo(zipfile, entry, destDir)
289
- });
290
-
291
- if (res === false) {
292
- return zipfile.emit('end');
293
- }
294
-
295
- zipfile.readEntry();
288
+ // Open a zip file and start reading entries
289
+ const zipfile = await openZip(zipFilePath, { lazyEntries: true });
290
+ const zipReadStreamPromise = new bluebird_1.default((resolve, reject) => {
291
+ zipfile.once('end', resolve);
292
+ zipfile.once('error', reject);
293
+ // On each entry, call 'onEntry' and then read the next entry
294
+ zipfile.on('entry', async (entry) => {
295
+ const res = await onEntry({
296
+ entry,
297
+ extractEntryTo: async (destDir) => await _extractEntryTo(zipfile, entry, destDir),
298
+ });
299
+ if (res === false) {
300
+ return zipfile.emit('end');
301
+ }
302
+ zipfile.readEntry();
303
+ });
296
304
  });
297
- });
298
- zipfile.readEntry();
299
- return await zipReadStreamPromise;
305
+ zipfile.readEntry();
306
+ // Wait for the entries to finish being iterated through
307
+ return await zipReadStreamPromise;
300
308
  }
301
-
302
- async function toInMemoryZip(srcPath, opts = {}) {
303
- if (!(await _fs2.default.exists(srcPath))) {
304
- throw new Error(`No such file or folder: ${srcPath}`);
305
- }
306
-
307
- const {
308
- isMetered = true,
309
- encodeToBase64 = false,
310
- maxSize = 1 * _util.GiB,
311
- level = 9
312
- } = opts;
313
- const resultBuffers = [];
314
- let resultBuffersSize = 0;
315
- const resultWriteStream = new _stream.default.Writable({
316
- write: (buffer, encoding, next) => {
317
- resultBuffers.push(buffer);
318
- resultBuffersSize += buffer.length;
319
-
320
- if (maxSize > 0 && resultBuffersSize > maxSize) {
321
- resultWriteStream.emit('error', new Error(`The size of the resulting ` + `archive must not be greater than ${(0, _util.toReadableSizeString)(maxSize)}`));
322
- }
323
-
324
- next();
325
- }
326
- });
327
- const archive = (0, _archiver.default)('zip', {
328
- zlib: {
329
- level
309
+ exports.readEntries = readEntries;
310
+ /**
311
+ * @typedef ZipOptions
312
+ * @property {boolean} encodeToBase64 [false] Whether to encode
313
+ * the resulting archive to a base64-encoded string
314
+ * @property {boolean} isMetered [true] Whether to log the actual
315
+ * archiver performance
316
+ * @property {number} maxSize [1073741824] The maximum size of
317
+ * the resulting archive in bytes. This is set to 1GB by default, because
318
+ * Appium limits the maximum HTTP body size to 1GB. Also, the NodeJS heap
319
+ * size must be enough to keep the resulting object (usually this size is
320
+ * limited to 1.4 GB)
321
+ * @property {number} level [9] The compression level. The maximum
322
+ * level is 9 (the best compression, worst performance). The minimum
323
+ * compression level is 0 (no compression).
324
+ */
325
+ /**
326
+ * Converts contents of local directory to an in-memory .zip buffer
327
+ *
328
+ * @param {string} srcPath The full path to the folder or file being zipped
329
+ * @param {ZipOptions} opts Zipping options
330
+ * @returns {Promise<Buffer>} Zipped (and encoded if `encodeToBase64` is truthy)
331
+ * content of the source path as memory buffer
332
+ * @throws {Error} if there was an error while reading the source
333
+ * or the source is too big
334
+ */
335
+ async function toInMemoryZip(srcPath, opts = /** @type {ZipOptions} */ ({})) {
336
+ if (!(await fs_2.default.exists(srcPath))) {
337
+ throw new Error(`No such file or folder: ${srcPath}`);
330
338
  }
331
- });
332
- let srcSize = null;
333
- const base64EncoderStream = encodeToBase64 ? new _base64Stream.Base64Encode() : null;
334
- const resultWriteStreamPromise = new _bluebird.default((resolve, reject) => {
335
- resultWriteStream.once('error', e => {
336
- if (base64EncoderStream) {
337
- archive.unpipe(base64EncoderStream);
338
- base64EncoderStream.unpipe(resultWriteStream);
339
- } else {
340
- archive.unpipe(resultWriteStream);
341
- }
342
-
343
- archive.abort();
344
- archive.destroy();
345
- reject(e);
339
+ const { isMetered = true, encodeToBase64 = false, maxSize = 1 * util_1.GiB, level = 9 } = opts;
340
+ const resultBuffers = [];
341
+ let resultBuffersSize = 0;
342
+ // Create a writable stream that zip buffers will be streamed to
343
+ const resultWriteStream = new stream_1.default.Writable({
344
+ write: (buffer, encoding, next) => {
345
+ resultBuffers.push(buffer);
346
+ resultBuffersSize += buffer.length;
347
+ if (maxSize > 0 && resultBuffersSize > maxSize) {
348
+ resultWriteStream.emit('error', new Error(`The size of the resulting ` +
349
+ `archive must not be greater than ${(0, util_1.toReadableSizeString)(maxSize)}`));
350
+ }
351
+ next();
352
+ },
353
+ });
354
+ // Zip 'srcDir' and stream it to the above writable stream
355
+ const archive = (0, archiver_1.default)('zip', {
356
+ zlib: { level },
346
357
  });
347
- resultWriteStream.once('finish', () => {
348
- srcSize = archive.pointer();
349
- resolve();
358
+ let srcSize = null;
359
+ const base64EncoderStream = encodeToBase64 ? new base64_stream_1.Base64Encode() : null;
360
+ const resultWriteStreamPromise = new bluebird_1.default((resolve, reject) => {
361
+ resultWriteStream.once('error', (e) => {
362
+ if (base64EncoderStream) {
363
+ archive.unpipe(base64EncoderStream);
364
+ base64EncoderStream.unpipe(resultWriteStream);
365
+ }
366
+ else {
367
+ archive.unpipe(resultWriteStream);
368
+ }
369
+ archive.abort();
370
+ archive.destroy();
371
+ reject(e);
372
+ });
373
+ resultWriteStream.once('finish', () => {
374
+ srcSize = archive.pointer();
375
+ resolve();
376
+ });
350
377
  });
351
- });
352
- const archiveStreamPromise = new _bluebird.default((resolve, reject) => {
353
- archive.once('finish', resolve);
354
- archive.once('error', e => reject(new Error(`Failed to archive '${srcPath}': ${e.message}`)));
355
- });
356
- const timer = isMetered ? new _timing.default().start() : null;
357
-
358
- if ((await _fs2.default.stat(srcPath)).isDirectory()) {
359
- archive.directory(srcPath, false);
360
- } else {
361
- archive.file(srcPath, {
362
- name: _path.default.basename(srcPath)
378
+ const archiveStreamPromise = new bluebird_1.default((resolve, reject) => {
379
+ archive.once('finish', resolve);
380
+ archive.once('error', (e) => reject(new Error(`Failed to archive '${srcPath}': ${e.message}`)));
363
381
  });
364
- }
365
-
366
- if (base64EncoderStream) {
367
- archive.pipe(base64EncoderStream);
368
- base64EncoderStream.pipe(resultWriteStream);
369
- } else {
370
- archive.pipe(resultWriteStream);
371
- }
372
-
373
- archive.finalize();
374
- await _bluebird.default.all([archiveStreamPromise, resultWriteStreamPromise]);
375
-
376
- if (timer) {
377
- _logger.default.debug(`Zipped ${encodeToBase64 ? 'and base64-encoded ' : ''}` + `'${_path.default.basename(srcPath)}' ` + (srcSize ? `(${(0, _util.toReadableSizeString)(srcSize)}) ` : '') + `in ${timer.getDuration().asSeconds.toFixed(3)}s ` + `(compression level: ${level})`);
378
- }
379
-
380
- return Buffer.concat(resultBuffers);
382
+ const timer = isMetered ? new timing_1.default().start() : null;
383
+ if ((await fs_2.default.stat(srcPath)).isDirectory()) {
384
+ archive.directory(srcPath, false);
385
+ }
386
+ else {
387
+ archive.file(srcPath, {
388
+ name: path_1.default.basename(srcPath),
389
+ });
390
+ }
391
+ if (base64EncoderStream) {
392
+ archive.pipe(base64EncoderStream);
393
+ base64EncoderStream.pipe(resultWriteStream);
394
+ }
395
+ else {
396
+ archive.pipe(resultWriteStream);
397
+ }
398
+ archive.finalize();
399
+ // Wait for the streams to finish
400
+ await bluebird_1.default.all([archiveStreamPromise, resultWriteStreamPromise]);
401
+ if (timer) {
402
+ logger_1.default.debug(`Zipped ${encodeToBase64 ? 'and base64-encoded ' : ''}` +
403
+ `'${path_1.default.basename(srcPath)}' ` +
404
+ (srcSize ? `(${(0, util_1.toReadableSizeString)(srcSize)}) ` : '') +
405
+ `in ${timer.getDuration().asSeconds.toFixed(3)}s ` +
406
+ `(compression level: ${level})`);
407
+ }
408
+ // Return the array of zip buffers concatenated into one buffer
409
+ return Buffer.concat(resultBuffers);
381
410
  }
382
-
411
+ exports.toInMemoryZip = toInMemoryZip;
412
+ /**
413
+ * Verifies whether the given file is a valid ZIP archive
414
+ *
415
+ * @param {string} filePath - Full path to the file
416
+ * @throws {Error} If the file does not exist or is not a valid ZIP archive
417
+ */
383
418
  async function assertValidZip(filePath) {
384
- if (!(await _fs2.default.exists(filePath))) {
385
- throw new Error(`The file at '${filePath}' does not exist`);
386
- }
387
-
388
- const {
389
- size
390
- } = await _fs2.default.stat(filePath);
391
-
392
- if (size < 4) {
393
- throw new Error(`The file at '${filePath}' is too small to be a ZIP archive`);
394
- }
395
-
396
- const fd = await _fs2.default.open(filePath, 'r');
397
-
398
- try {
399
- const buffer = Buffer.alloc(ZIP_MAGIC.length);
400
- await _fs2.default.read(fd, buffer, 0, ZIP_MAGIC.length, 0);
401
- const signature = buffer.toString('ascii');
402
-
403
- if (signature !== ZIP_MAGIC) {
404
- throw new Error(`The file signature '${signature}' of '${filePath}' ` + `is not equal to the expected ZIP archive signature '${ZIP_MAGIC}'`);
419
+ if (!(await fs_2.default.exists(filePath))) {
420
+ throw new Error(`The file at '${filePath}' does not exist`);
405
421
  }
406
-
407
- return true;
408
- } finally {
409
- await _fs2.default.close(fd);
410
- }
411
- }
412
-
413
- async function toArchive(dstPath, src = {}, opts = {}) {
414
- const {
415
- level = 9
416
- } = opts;
417
- const {
418
- pattern = '**/*',
419
- cwd = _path.default.dirname(dstPath),
420
- ignore = []
421
- } = src;
422
- const archive = (0, _archiver.default)('zip', {
423
- zlib: {
424
- level
422
+ const { size } = await fs_2.default.stat(filePath);
423
+ if (size < 4) {
424
+ throw new Error(`The file at '${filePath}' is too small to be a ZIP archive`);
425
+ }
426
+ const fd = await fs_2.default.open(filePath, 'r');
427
+ try {
428
+ const buffer = Buffer.alloc(ZIP_MAGIC.length);
429
+ await fs_2.default.read(fd, buffer, 0, ZIP_MAGIC.length, 0);
430
+ const signature = buffer.toString('ascii');
431
+ if (signature !== ZIP_MAGIC) {
432
+ throw new Error(`The file signature '${signature}' of '${filePath}' ` +
433
+ `is not equal to the expected ZIP archive signature '${ZIP_MAGIC}'`);
434
+ }
435
+ return true;
436
+ }
437
+ finally {
438
+ await fs_2.default.close(fd);
425
439
  }
426
- });
427
-
428
- const stream = _fs2.default.createWriteStream(dstPath);
429
-
430
- return await new _bluebird.default((resolve, reject) => {
431
- archive.glob(pattern, {
432
- cwd,
433
- ignore
434
- }).on('error', reject).pipe(stream);
435
- stream.on('error', e => {
436
- archive.unpipe(stream);
437
- archive.abort();
438
- archive.destroy();
439
- reject(e);
440
- }).on('finish', resolve);
441
- archive.finalize();
442
- });
443
440
  }
444
-
445
- const getExecutablePath = _lodash.default.memoize(async function getExecutablePath(binaryName) {
446
- const fullPath = await _fs2.default.which(binaryName);
447
-
448
- _logger.default.debug(`Found '${binaryName}' at '${fullPath}'`);
449
-
450
- return fullPath;
441
+ exports.assertValidZip = assertValidZip;
442
+ /**
443
+ * @typedef ZipCompressionOptions
444
+ * @property {number} level [9] - Compression level in range 0..9
445
+ * (greater numbers mean better compression, but longer processing time)
446
+ */
447
+ /**
448
+ * @typedef ZipSourceOptions
449
+ * @property {string} pattern ['**\/*'] - GLOB pattern for compression
450
+ * @property {string} cwd - The source root folder (the parent folder of
451
+ * the destination file by default)
452
+ * @property {string[]} [ignore] - The list of ignored patterns
453
+ */
454
+ /**
455
+ * Creates an archive based on the given glob pattern
456
+ *
457
+ * @param {string} dstPath - The resulting archive path
458
+ * @param {ZipSourceOptions} src - Source options
459
+ * @param {ZipCompressionOptions} opts - Compression options
460
+ * @throws {Error} If there was an error while creating the archive
461
+ */
462
+ async function toArchive(dstPath, src = /** @type {ZipSourceOptions} */ ({}), opts = /** @type {ZipCompressionOptions} */ ({})) {
463
+ const { level = 9 } = opts;
464
+ const { pattern = '**/*', cwd = path_1.default.dirname(dstPath), ignore = [] } = src;
465
+ const archive = (0, archiver_1.default)('zip', { zlib: { level } });
466
+ const stream = fs_2.default.createWriteStream(dstPath);
467
+ return await new bluebird_1.default((resolve, reject) => {
468
+ archive
469
+ .glob(pattern, {
470
+ cwd,
471
+ ignore,
472
+ })
473
+ .on('error', reject)
474
+ .pipe(stream);
475
+ stream
476
+ .on('error', (e) => {
477
+ archive.unpipe(stream);
478
+ archive.abort();
479
+ archive.destroy();
480
+ reject(e);
481
+ })
482
+ .on('finish', resolve);
483
+ archive.finalize();
484
+ });
485
+ }
486
+ exports.toArchive = toArchive;
487
+ /**
488
+ * Finds and memoizes the full path to the given executable.
489
+ * Rejects if it is not found.
490
+ */
491
+ const getExecutablePath = lodash_1.default.memoize(
492
+ /**
493
+ * @returns {Promise<string>} Full Path to the executable
494
+ */
495
+ async function getExecutablePath(binaryName) {
496
+ const fullPath = await fs_2.default.which(binaryName);
497
+ logger_1.default.debug(`Found '${binaryName}' at '${fullPath}'`);
498
+ return fullPath;
451
499
  });
452
-
453
- var _default = {
454
- extractAllTo,
455
- readEntries,
456
- toInMemoryZip,
457
- assertValidZip,
458
- toArchive
500
+ exports.default = {
501
+ extractAllTo,
502
+ readEntries,
503
+ toInMemoryZip,
504
+ assertValidZip,
505
+ toArchive,
459
506
  };
460
- exports.default = _default;
461
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJvcGVuWmlwIiwiQiIsInByb21pc2lmeSIsInlhdXpsIiwib3BlbiIsInBpcGVsaW5lIiwic3RyZWFtIiwiWklQX01BR0lDIiwiSUZNVCIsIklGRElSIiwiSUZMTksiLCJaaXBFeHRyYWN0b3IiLCJ6aXBmaWxlIiwiY29uc3RydWN0b3IiLCJzb3VyY2VQYXRoIiwib3B0cyIsInppcFBhdGgiLCJjYW5jZWxlZCIsImV4dHJhY3RGaWxlTmFtZSIsImVudHJ5IiwiXyIsImlzQnVmZmVyIiwiZmlsZU5hbWUiLCJ0b1N0cmluZyIsImZpbGVOYW1lc0VuY29kaW5nIiwiZXh0cmFjdCIsImRpciIsImxhenlFbnRyaWVzIiwiZGVjb2RlU3RyaW5ncyIsInJlc29sdmUiLCJyZWplY3QiLCJvbiIsImVyciIsInJlYWRFbnRyeSIsInN0YXJ0c1dpdGgiLCJkZXN0RGlyIiwicGF0aCIsImRpcm5hbWUiLCJqb2luIiwiZnMiLCJta2RpciIsInJlY3Vyc2l2ZSIsImNhbm9uaWNhbERlc3REaXIiLCJyZWFscGF0aCIsInJlbGF0aXZlRGVzdERpciIsInJlbGF0aXZlIiwic3BsaXQiLCJzZXAiLCJpbmNsdWRlcyIsIkVycm9yIiwiZXh0cmFjdEVudHJ5IiwiY2xvc2UiLCJkZXN0IiwibW9kZSIsImV4dGVybmFsRmlsZUF0dHJpYnV0ZXMiLCJpc1N5bWxpbmsiLCJpc0RpciIsImVuZHNXaXRoIiwidmVyc2lvbk1hZGVCeSIsInByb2NNb2RlIiwiZ2V0RXh0cmFjdGVkTW9kZSIsIm1rZGlyT3B0aW9ucyIsIm9wZW5SZWFkU3RyZWFtIiwiYmluZCIsInJlYWRTdHJlYW0iLCJsaW5rIiwiZ2V0U3RyZWFtIiwic3ltbGluayIsImNyZWF0ZVdyaXRlU3RyZWFtIiwiZW50cnlNb2RlIiwiZGVmYXVsdERpck1vZGUiLCJkZWZhdWx0RmlsZU1vZGUiLCJwYXJzZUludCIsImV4dHJhY3RBbGxUbyIsInppcEZpbGVQYXRoIiwiaXNBYnNvbHV0ZSIsInVzZVN5c3RlbVVuemlwIiwiZXh0cmFjdFdpdGhTeXN0ZW1VbnppcCIsImxvZyIsIndhcm4iLCJzdGRlcnIiLCJtZXNzYWdlIiwiZXh0cmFjdG9yIiwiaXNXaW5kb3dzSG9zdCIsImlzV2luZG93cyIsImV4ZWN1dGFibGVQYXRoIiwiZ2V0RXhlY3V0YWJsZVBhdGgiLCJlIiwiZXhlYyIsIl9leHRyYWN0RW50cnlUbyIsInppcEZpbGUiLCJkc3RQYXRoIiwidGVzdCIsImV4aXN0cyIsIm1rZGlycCIsIndyaXRlU3RyZWFtIiwiZmxhZ3MiLCJ3cml0ZVN0cmVhbVByb21pc2UiLCJvbmNlIiwiemlwUmVhZFN0cmVhbSIsInppcFJlYWRTdHJlYW1Qcm9taXNlIiwicGlwZSIsImFsbCIsInJlYWRFbnRyaWVzIiwib25FbnRyeSIsInJlcyIsImV4dHJhY3RFbnRyeVRvIiwiZW1pdCIsInRvSW5NZW1vcnlaaXAiLCJzcmNQYXRoIiwiaXNNZXRlcmVkIiwiZW5jb2RlVG9CYXNlNjQiLCJtYXhTaXplIiwiR2lCIiwibGV2ZWwiLCJyZXN1bHRCdWZmZXJzIiwicmVzdWx0QnVmZmVyc1NpemUiLCJyZXN1bHRXcml0ZVN0cmVhbSIsIldyaXRhYmxlIiwid3JpdGUiLCJidWZmZXIiLCJlbmNvZGluZyIsIm5leHQiLCJwdXNoIiwibGVuZ3RoIiwidG9SZWFkYWJsZVNpemVTdHJpbmciLCJhcmNoaXZlIiwiYXJjaGl2ZXIiLCJ6bGliIiwic3JjU2l6ZSIsImJhc2U2NEVuY29kZXJTdHJlYW0iLCJCYXNlNjRFbmNvZGUiLCJyZXN1bHRXcml0ZVN0cmVhbVByb21pc2UiLCJ1bnBpcGUiLCJhYm9ydCIsImRlc3Ryb3kiLCJwb2ludGVyIiwiYXJjaGl2ZVN0cmVhbVByb21pc2UiLCJ0aW1lciIsIlRpbWVyIiwic3RhcnQiLCJzdGF0IiwiaXNEaXJlY3RvcnkiLCJkaXJlY3RvcnkiLCJmaWxlIiwibmFtZSIsImJhc2VuYW1lIiwiZmluYWxpemUiLCJkZWJ1ZyIsImdldER1cmF0aW9uIiwiYXNTZWNvbmRzIiwidG9GaXhlZCIsIkJ1ZmZlciIsImNvbmNhdCIsImFzc2VydFZhbGlkWmlwIiwiZmlsZVBhdGgiLCJzaXplIiwiZmQiLCJhbGxvYyIsInJlYWQiLCJzaWduYXR1cmUiLCJ0b0FyY2hpdmUiLCJzcmMiLCJwYXR0ZXJuIiwiY3dkIiwiaWdub3JlIiwiZ2xvYiIsIm1lbW9pemUiLCJiaW5hcnlOYW1lIiwiZnVsbFBhdGgiLCJ3aGljaCJdLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi96aXAuanMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCBCIGZyb20gJ2JsdWViaXJkJztcbmltcG9ydCB5YXV6bCBmcm9tICd5YXV6bCc7XG5pbXBvcnQgYXJjaGl2ZXIgZnJvbSAnYXJjaGl2ZXInO1xuaW1wb3J0IHtjcmVhdGVXcml0ZVN0cmVhbX0gZnJvbSAnZnMnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgc3RyZWFtIGZyb20gJ3N0cmVhbSc7XG5pbXBvcnQgZnMgZnJvbSAnLi9mcyc7XG5pbXBvcnQge2lzV2luZG93c30gZnJvbSAnLi9zeXN0ZW0nO1xuaW1wb3J0IHtCYXNlNjRFbmNvZGV9IGZyb20gJ2Jhc2U2NC1zdHJlYW0nO1xuaW1wb3J0IHt0b1JlYWRhYmxlU2l6ZVN0cmluZywgR2lCfSBmcm9tICcuL3V0aWwnO1xuaW1wb3J0IFRpbWVyIGZyb20gJy4vdGltaW5nJztcbmltcG9ydCBsb2cgZnJvbSAnLi9sb2dnZXInO1xuaW1wb3J0IGdldFN0cmVhbSBmcm9tICdnZXQtc3RyZWFtJztcbmltcG9ydCB7ZXhlY30gZnJvbSAndGVlbl9wcm9jZXNzJztcblxuLyoqXG4gKiBAdHlwZSB7KHBhdGg6IHN0cmluZywgb3B0aW9ucz86IHlhdXpsLk9wdGlvbnMpID0+IFByb21pc2U8eWF1emwuWmlwRmlsZT59XG4gKi9cbmNvbnN0IG9wZW5aaXAgPSBCLnByb21pc2lmeSh5YXV6bC5vcGVuKTtcbi8qKlxuICogQHR5cGUgeyhzb3VyY2U6IE5vZGVKUy5SZWFkYWJsZVN0cmVhbSwgZGVzdGluYXRpb246IE5vZGVKUy5Xcml0YWJsZVN0cmVhbSkgPT4gUHJvbWlzZTxOb2RlSlMuV3JpdGFibGVTdHJlYW0+fVxuICovXG5jb25zdCBwaXBlbGluZSA9IEIucHJvbWlzaWZ5KHN0cmVhbS5waXBlbGluZSk7XG5jb25zdCBaSVBfTUFHSUMgPSAnUEsnO1xuY29uc3QgSUZNVCA9IDYxNDQwO1xuY29uc3QgSUZESVIgPSAxNjM4NDtcbmNvbnN0IElGTE5LID0gNDA5NjA7XG5cbi8vIFRoaXMgY2xhc3MgaXMgbW9zdGx5IGNvcGllZCBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9tYXhvZ2Rlbi9leHRyYWN0LXppcC9ibG9iL21hc3Rlci9pbmRleC5qc1xuY2xhc3MgWmlwRXh0cmFjdG9yIHtcbiAgLyoqIEB0eXBlIHt5YXV6bC5aaXBGaWxlfSAqL1xuICB6aXBmaWxlO1xuXG4gIGNvbnN0cnVjdG9yKHNvdXJjZVBhdGgsIG9wdHMgPSB7fSkge1xuICAgIHRoaXMuemlwUGF0aCA9IHNvdXJjZVBhdGg7XG4gICAgdGhpcy5vcHRzID0gb3B0cztcbiAgICB0aGlzLmNhbmNlbGVkID0gZmFsc2U7XG4gIH1cblxuICBleHRyYWN0RmlsZU5hbWUoZW50cnkpIHtcbiAgICByZXR1cm4gXy5pc0J1ZmZlcihlbnRyeS5maWxlTmFtZSlcbiAgICAgID8gZW50cnkuZmlsZU5hbWUudG9TdHJpbmcodGhpcy5vcHRzLmZpbGVOYW1lc0VuY29kaW5nKVxuICAgICAgOiBlbnRyeS5maWxlTmFtZTtcbiAgfVxuXG4gIGFzeW5jIGV4dHJhY3QoKSB7XG4gICAgY29uc3Qge2RpciwgZmlsZU5hbWVzRW5jb2Rpbmd9ID0gdGhpcy5vcHRzO1xuICAgIHRoaXMuemlwZmlsZSA9IGF3YWl0IG9wZW5aaXAodGhpcy56aXBQYXRoLCB7XG4gICAgICBsYXp5RW50cmllczogdHJ1ZSxcbiAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS90aGVqb3Nod29sZmUveWF1emwvY29tbWl0L2NjNzQ1NWFjNzg5YmE4NDk3MzE4NGU1ZWJkZTA1ODFjZGM0YzNiMzkjZGlmZi0wNGM2ZTkwZmFhYzI2NzVhYTg5ZTIxNzZkMmVlYzdkOFI5NVxuICAgICAgZGVjb2RlU3RyaW5nczogIWZpbGVOYW1lc0VuY29kaW5nLFxuICAgIH0pO1xuICAgIHRoaXMuY2FuY2VsZWQgPSBmYWxzZTtcblxuICAgIHJldHVybiBuZXcgQigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLnppcGZpbGUub24oJ2Vycm9yJywgKGVycikgPT4ge1xuICAgICAgICB0aGlzLmNhbmNlbGVkID0gdHJ1ZTtcbiAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICB9KTtcbiAgICAgIHRoaXMuemlwZmlsZS5yZWFkRW50cnkoKTtcblxuICAgICAgdGhpcy56aXBmaWxlLm9uKCdjbG9zZScsICgpID0+IHtcbiAgICAgICAgaWYgKCF0aGlzLmNhbmNlbGVkKSB7XG4gICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgdGhpcy56aXBmaWxlLm9uKCdlbnRyeScsIGFzeW5jIChlbnRyeSkgPT4ge1xuICAgICAgICBpZiAodGhpcy5jYW5jZWxlZCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGZpbGVOYW1lID0gdGhpcy5leHRyYWN0RmlsZU5hbWUoZW50cnkpO1xuICAgICAgICBpZiAoZmlsZU5hbWUuc3RhcnRzV2l0aCgnX19NQUNPU1gvJykpIHtcbiAgICAgICAgICB0aGlzLnppcGZpbGUucmVhZEVudHJ5KCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZGVzdERpciA9IHBhdGguZGlybmFtZShwYXRoLmpvaW4oZGlyLCBmaWxlTmFtZSkpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGZzLm1rZGlyKGRlc3REaXIsIHtyZWN1cnNpdmU6IHRydWV9KTtcblxuICAgICAgICAgIGNvbnN0IGNhbm9uaWNhbERlc3REaXIgPSBhd2FpdCBmcy5yZWFscGF0aChkZXN0RGlyKTtcbiAgICAgICAgICBjb25zdCByZWxhdGl2ZURlc3REaXIgPSBwYXRoLnJlbGF0aXZlKGRpciwgY2Fub25pY2FsRGVzdERpcik7XG5cbiAgICAgICAgICBpZiAocmVsYXRpdmVEZXN0RGlyLnNwbGl0KHBhdGguc2VwKS5pbmNsdWRlcygnLi4nKSkge1xuICAgICAgICAgICAgbmV3IEVycm9yKFxuICAgICAgICAgICAgICBgT3V0IG9mIGJvdW5kIHBhdGggXCIke2Nhbm9uaWNhbERlc3REaXJ9XCIgZm91bmQgd2hpbGUgcHJvY2Vzc2luZyBmaWxlICR7ZmlsZU5hbWV9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBhd2FpdCB0aGlzLmV4dHJhY3RFbnRyeShlbnRyeSk7XG4gICAgICAgICAgdGhpcy56aXBmaWxlLnJlYWRFbnRyeSgpO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICB0aGlzLmNhbmNlbGVkID0gdHJ1ZTtcbiAgICAgICAgICB0aGlzLnppcGZpbGUuY2xvc2UoKTtcbiAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBleHRyYWN0RW50cnkoZW50cnkpIHtcbiAgICBpZiAodGhpcy5jYW5jZWxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHtkaXJ9ID0gdGhpcy5vcHRzO1xuXG4gICAgY29uc3QgZmlsZU5hbWUgPSB0aGlzLmV4dHJhY3RGaWxlTmFtZShlbnRyeSk7XG4gICAgY29uc3QgZGVzdCA9IHBhdGguam9pbihkaXIsIGZpbGVOYW1lKTtcblxuICAgIC8vIGNvbnZlcnQgZXh0ZXJuYWwgZmlsZSBhdHRyIGludCBpbnRvIGEgZnMgc3RhdCBtb2RlIGludFxuICAgIGNvbnN0IG1vZGUgPSAoZW50cnkuZXh0ZXJuYWxGaWxlQXR0cmlidXRlcyA+PiAxNikgJiAweGZmZmY7XG4gICAgLy8gY2hlY2sgaWYgaXQncyBhIHN5bWxpbmsgb3IgZGlyICh1c2luZyBzdGF0IG1vZGUgY29uc3RhbnRzKVxuICAgIGNvbnN0IGlzU3ltbGluayA9IChtb2RlICYgSUZNVCkgPT09IElGTE5LO1xuICAgIGNvbnN0IGlzRGlyID1cbiAgICAgIChtb2RlICYgSUZNVCkgPT09IElGRElSIHx8XG4gICAgICAvLyBGYWlsc2FmZSwgYm9ycm93ZWQgZnJvbSBqc1ppcFxuICAgICAgZmlsZU5hbWUuZW5kc1dpdGgoJy8nKSB8fFxuICAgICAgLy8gY2hlY2sgZm9yIHdpbmRvd3Mgd2VpcmQgd2F5IG9mIHNwZWNpZnlpbmcgYSBkaXJlY3RvcnlcbiAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tYXhvZ2Rlbi9leHRyYWN0LXppcC9pc3N1ZXMvMTMjaXNzdWVjb21tZW50LTE1NDQ5NDU2NlxuICAgICAgKGVudHJ5LnZlcnNpb25NYWRlQnkgPj4gOCA9PT0gMCAmJiBlbnRyeS5leHRlcm5hbEZpbGVBdHRyaWJ1dGVzID09PSAxNik7XG4gICAgY29uc3QgcHJvY01vZGUgPSB0aGlzLmdldEV4dHJhY3RlZE1vZGUobW9kZSwgaXNEaXIpICYgMG83Nzc7XG4gICAgLy8gYWx3YXlzIGVuc3VyZSBmb2xkZXJzIGFyZSBjcmVhdGVkXG4gICAgY29uc3QgZGVzdERpciA9IGlzRGlyID8gZGVzdCA6IHBhdGguZGlybmFtZShkZXN0KTtcbiAgICBjb25zdCBta2Rpck9wdGlvbnMgPSB7cmVjdXJzaXZlOiB0cnVlfTtcbiAgICBpZiAoaXNEaXIpIHtcbiAgICAgIG1rZGlyT3B0aW9ucy5tb2RlID0gcHJvY01vZGU7XG4gICAgfVxuICAgIGF3YWl0IGZzLm1rZGlyKGRlc3REaXIsIG1rZGlyT3B0aW9ucyk7XG4gICAgaWYgKGlzRGlyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLyoqIEB0eXBlIHsoZW50cnk6IHlhdXpsLkVudHJ5KSA9PiBQcm9taXNlPE5vZGVKUy5SZWFkYWJsZVN0cmVhbT59ICovXG4gICAgY29uc3Qgb3BlblJlYWRTdHJlYW0gPSBCLnByb21pc2lmeSh0aGlzLnppcGZpbGUub3BlblJlYWRTdHJlYW0uYmluZCh0aGlzLnppcGZpbGUpKTtcbiAgICBjb25zdCByZWFkU3RyZWFtID0gYXdhaXQgb3BlblJlYWRTdHJlYW0oZW50cnkpO1xuICAgIGlmIChpc1N5bWxpbmspIHtcbiAgICAgIGNvbnN0IGxpbmsgPSBhd2FpdCBnZXRTdHJlYW0ocmVhZFN0cmVhbSk7XG4gICAgICBhd2FpdCBmcy5zeW1saW5rKGxpbmssIGRlc3QpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCBwaXBlbGluZShyZWFkU3RyZWFtLCBmcy5jcmVhdGVXcml0ZVN0cmVhbShkZXN0LCB7bW9kZTogcHJvY01vZGV9KSk7XG4gICAgfVxuICB9XG5cbiAgZ2V0RXh0cmFjdGVkTW9kZShlbnRyeU1vZGUsIGlzRGlyKSB7XG4gICAgY29uc3Qge2RlZmF1bHREaXJNb2RlLCBkZWZhdWx0RmlsZU1vZGV9ID0gdGhpcy5vcHRzO1xuXG4gICAgbGV0IG1vZGUgPSBlbnRyeU1vZGU7XG4gICAgLy8gU2V0IGRlZmF1bHRzLCBpZiBuZWNlc3NhcnlcbiAgICBpZiAobW9kZSA9PT0gMCkge1xuICAgICAgaWYgKGlzRGlyKSB7XG4gICAgICAgIGlmIChkZWZhdWx0RGlyTW9kZSkge1xuICAgICAgICAgIG1vZGUgPSBwYXJzZUludChkZWZhdWx0RGlyTW9kZSwgMTApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFtb2RlKSB7XG4gICAgICAgICAgbW9kZSA9IDBvNzU1O1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoZGVmYXVsdEZpbGVNb2RlKSB7XG4gICAgICAgICAgbW9kZSA9IHBhcnNlSW50KGRlZmF1bHRGaWxlTW9kZSwgMTApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFtb2RlKSB7XG4gICAgICAgICAgbW9kZSA9IDBvNjQ0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGU7XG4gIH1cbn1cblxuLyoqXG4gKiBAdHlwZWRlZiBFeHRyYWN0QWxsT3B0aW9uc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IFtmaWxlTmFtZXNFbmNvZGluZ10gVGhlIGVuY29kaW5nIHRvIHVzZSBmb3IgZXh0cmFjdGVkIGZpbGUgbmFtZXMuXG4gKiBGb3IgWklQIGFyY2hpdmVzIGNyZWF0ZWQgb24gTWFjT1MgaXQgaXMgdXN1YWxseSBleHBlY3RlZCB0byBiZSBgdXRmOGAuXG4gKiBCeSBkZWZhdWx0IGl0IGlzIGF1dG9kZXRlY3RlZCBiYXNlZCBvbiB0aGUgZW50cnkgbWV0YWRhdGEgYW5kIGlzIG9ubHkgbmVlZGVkIHRvIGJlIHNldCBleHBsaWNpdGx5XG4gKiBpZiB0aGUgcGFydGljdWxhciBhcmNoaXZlIGRvZXMgbm90IGNvbXBseSB0byB0aGUgc3RhbmRhcmRzLCB3aGljaCBsZWFkcyB0byBjb3JydXB0ZWQgZmlsZSBuYW1lc1xuICogYWZ0ZXIgZXh0cmFjdGlvbi4gT25seSBhcHBsaWNhYmxlIGlmIHN5c3RlbSB1bnppcCBiaW5hcnkgaXMgTk9UIGJlaW5nIHVzZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFt1c2VTeXN0ZW1VbnppcF0gSWYgdHJ1ZSwgYXR0ZW1wdCB0byB1c2Ugc3lzdGVtIHVuemlwOyBpZiB0aGlzIGZhaWxzLFxuICogZmFsbGJhY2sgdG8gdGhlIEpTIHVuemlwIGltcGxlbWVudGF0aW9uLlxuICovXG5cbi8qKlxuICogRXh0cmFjdCB6aXBmaWxlIHRvIGEgZGlyZWN0b3J5XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHppcEZpbGVQYXRoIFRoZSBmdWxsIHBhdGggdG8gdGhlIHNvdXJjZSBaSVAgZmlsZVxuICogQHBhcmFtIHtzdHJpbmd9IGRlc3REaXIgVGhlIGZ1bGwgcGF0aCB0byB0aGUgZGVzdGluYXRpb24gZm9sZGVyXG4gKiBAcGFyYW0ge0V4dHJhY3RBbGxPcHRpb25zfSBbb3B0c11cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZXh0cmFjdEFsbFRvKHppcEZpbGVQYXRoLCBkZXN0RGlyLCBvcHRzID0gLyoqIEB0eXBlIHtFeHRyYWN0QWxsT3B0aW9uc30gKi8gKHt9KSkge1xuICBpZiAoIXBhdGguaXNBYnNvbHV0ZShkZXN0RGlyKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVGFyZ2V0IHBhdGggJyR7ZGVzdERpcn0nIGlzIGV4cGVjdGVkIHRvIGJlIGFic29sdXRlYCk7XG4gIH1cblxuICBhd2FpdCBmcy5ta2RpcihkZXN0RGlyLCB7cmVjdXJzaXZlOiB0cnVlfSk7XG4gIGNvbnN0IGRpciA9IGF3YWl0IGZzLnJlYWxwYXRoKGRlc3REaXIpO1xuICBpZiAob3B0cy51c2VTeXN0ZW1VbnppcCkge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBleHRyYWN0V2l0aFN5c3RlbVVuemlwKHppcEZpbGVQYXRoLCBkaXIpO1xuICAgICAgcmV0dXJuO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgbG9nLndhcm4oJ3VuemlwIGZhaWxlZDsgZmFsbGluZyBiYWNrIHRvIEpTOiAlcycsIGVyci5zdGRlcnIgfHwgZXJyLm1lc3NhZ2UpO1xuICAgIH1cbiAgfVxuICBjb25zdCBleHRyYWN0b3IgPSBuZXcgWmlwRXh0cmFjdG9yKHppcEZpbGVQYXRoLCB7XG4gICAgLi4ub3B0cyxcbiAgICBkaXIsXG4gIH0pO1xuICBhd2FpdCBleHRyYWN0b3IuZXh0cmFjdCgpO1xufVxuXG4vKipcbiAqIEV4ZWN1dGVzIHN5c3RlbSB1bnppcCAoZS5nLiwgYC91c3IvYmluL3VuemlwYCkuIElmIGF2YWlsYWJsZSwgaXQgaXNcbiAqIHNpZ25pZmljYW50bHkgZmFzdGVyIHRoYW4gdGhlIEpTIGltcGxlbWVudGF0aW9uLlxuICogQnkgZGVmYXVsdCBhbGwgZmlsZXMgaW4gdGhlIGRlc3REaXIgZ2V0IG92ZXJyaWRkZW4gaWYgYWxyZWFkeSBleGlzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gemlwRmlsZVBhdGggVGhlIGZ1bGwgcGF0aCB0byB0aGUgc291cmNlIFpJUCBmaWxlXG4gKiBAcGFyYW0ge3N0cmluZ30gZGVzdERpciBUaGUgZnVsbCBwYXRoIHRvIHRoZSBkZXN0aW5hdGlvbiBmb2xkZXIuXG4gKiBUaGlzIGZvbGRlciBpcyBleHBlY3RlZCB0byBhbHJlYWR5IGV4aXN0IGJlZm9yZSBleHRyYWN0aW5nIHRoZSBhcmNoaXZlLlxuICovXG5hc3luYyBmdW5jdGlvbiBleHRyYWN0V2l0aFN5c3RlbVVuemlwKHppcEZpbGVQYXRoLCBkZXN0RGlyKSB7XG4gIGNvbnN0IGlzV2luZG93c0hvc3QgPSBpc1dpbmRvd3MoKTtcbiAgbGV0IGV4ZWN1dGFibGVQYXRoO1xuICB0cnkge1xuICAgIGV4ZWN1dGFibGVQYXRoID0gYXdhaXQgZ2V0RXhlY3V0YWJsZVBhdGgoaXNXaW5kb3dzSG9zdCA/ICdwb3dlcnNoZWxsLmV4ZScgOiAndW56aXAnKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGZpbmQgc3lzdGVtIHVuemlwJyk7XG4gIH1cblxuICBpZiAoaXNXaW5kb3dzSG9zdCkge1xuICAgIC8vIG9uIFdpbmRvd3Mgd2UgdXNlIFBvd2VyU2hlbGwgdG8gdW56aXAgZmlsZXNcbiAgICBhd2FpdCBleGVjKGV4ZWN1dGFibGVQYXRoLCBbXG4gICAgICAnLWNvbW1hbmQnLFxuICAgICAgJ0V4cGFuZC1BcmNoaXZlJyxcbiAgICAgICctTGl0ZXJhbFBhdGgnLFxuICAgICAgemlwRmlsZVBhdGgsXG4gICAgICAnLURlc3RpbmF0aW9uUGF0aCcsXG4gICAgICBkZXN0RGlyLFxuICAgICAgJy1Gb3JjZScsXG4gICAgXSk7XG4gIH0gZWxzZSB7XG4gICAgLy8gLXEgbWVhbnMgcXVpZXQgKG5vIHN0ZG91dClcbiAgICAvLyAtbyBtZWFucyBvdmVyd3JpdGVcbiAgICAvLyAtZCBpcyB0aGUgZGVzdCBkaXJcbiAgICBhd2FpdCBleGVjKGV4ZWN1dGFibGVQYXRoLCBbJy1xJywgJy1vJywgemlwRmlsZVBhdGgsICctZCcsIGRlc3REaXJdKTtcbiAgfVxufVxuXG4vKipcbiAqIEV4dHJhY3QgYSBzaW5nbGUgemlwIGVudHJ5IHRvIGEgZGlyZWN0b3J5XG4gKlxuICogQHBhcmFtIHt5YXV6bC5aaXBGaWxlfSB6aXBGaWxlIFRoZSBzb3VyY2UgWklQIHN0cmVhbVxuICogQHBhcmFtIHt5YXV6bC5FbnRyeX0gZW50cnkgVGhlIGVudHJ5IGluc3RhbmNlXG4gKiBAcGFyYW0ge3N0cmluZ30gZGVzdERpciBUaGUgZnVsbCBwYXRoIHRvIHRoZSBkZXN0aW5hdGlvbiBmb2xkZXJcbiAqL1xuYXN5bmMgZnVuY3Rpb24gX2V4dHJhY3RFbnRyeVRvKHppcEZpbGUsIGVudHJ5LCBkZXN0RGlyKSB7XG4gIGNvbnN0IGRzdFBhdGggPSBwYXRoLnJlc29sdmUoZGVzdERpciwgZW50cnkuZmlsZU5hbWUpO1xuXG4gIC8vIENyZWF0ZSBkZXN0IGRpcmVjdG9yeSBpZiBkb2Vzbid0IGV4aXN0IGFscmVhZHlcbiAgaWYgKC9cXC8kLy50ZXN0KGVudHJ5LmZpbGVOYW1lKSkge1xuICAgIGlmICghKGF3YWl0IGZzLmV4aXN0cyhkc3RQYXRoKSkpIHtcbiAgICAgIGF3YWl0IGZzLm1rZGlycChkc3RQYXRoKTtcbiAgICB9XG4gICAgcmV0dXJuO1xuICB9IGVsc2UgaWYgKCEoYXdhaXQgZnMuZXhpc3RzKHBhdGguZGlybmFtZShkc3RQYXRoKSkpKSB7XG4gICAgYXdhaXQgZnMubWtkaXJwKHBhdGguZGlybmFtZShkc3RQYXRoKSk7XG4gIH1cblxuICAvLyBDcmVhdGUgYSB3cml0ZSBzdHJlYW1cbiAgY29uc3Qgd3JpdGVTdHJlYW0gPSBjcmVhdGVXcml0ZVN0cmVhbShkc3RQYXRoLCB7ZmxhZ3M6ICd3J30pO1xuICBjb25zdCB3cml0ZVN0cmVhbVByb21pc2UgPSBuZXcgQigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgd3JpdGVTdHJlYW0ub25jZSgnZmluaXNoJywgcmVzb2x2ZSk7XG4gICAgd3JpdGVTdHJlYW0ub25jZSgnZXJyb3InLCByZWplY3QpO1xuICB9KTtcblxuICAvLyBDcmVhdGUgemlwUmVhZFN0cmVhbSBhbmQgcGlwZSBkYXRhIHRvIHRoZSB3cml0ZSBzdHJlYW1cbiAgLy8gKGZvciBzb21lIG9kZCByZWFzb24gQi5wcm9taXNpZnkgZG9lc24ndCB3b3JrIG9uIHppcGZpbGUub3BlblJlYWRTdHJlYW0sIGl0IGNhdXNlcyBhbiBlcnJvciAnY2xvc2VkJylcbiAgY29uc3QgemlwUmVhZFN0cmVhbSA9IGF3YWl0IG5ldyBCKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICB6aXBGaWxlLm9wZW5SZWFkU3RyZWFtKGVudHJ5LCAoZXJyLCByZWFkU3RyZWFtKSA9PiAoZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHJlYWRTdHJlYW0pKSk7XG4gIH0pO1xuICBjb25zdCB6aXBSZWFkU3RyZWFtUHJvbWlzZSA9IG5ldyBCKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICB6aXBSZWFkU3RyZWFtLm9uY2UoJ2VuZCcsIHJlc29sdmUpO1xuICAgIHppcFJlYWRTdHJlYW0ub25jZSgnZXJyb3InLCByZWplY3QpO1xuICB9KTtcbiAgemlwUmVhZFN0cmVhbS5waXBlKHdyaXRlU3RyZWFtKTtcblxuICAvLyBXYWl0IGZvciB0aGUgemlwUmVhZFN0cmVhbSBhbmQgd3JpdGVTdHJlYW0gdG8gZW5kIGJlZm9yZSByZXR1cm5pbmdcbiAgcmV0dXJuIGF3YWl0IEIuYWxsKFt6aXBSZWFkU3RyZWFtUHJvbWlzZSwgd3JpdGVTdHJlYW1Qcm9taXNlXSk7XG59XG5cbi8qKlxuICogQHR5cGVkZWYgWmlwRW50cnlcbiAqIEBwcm9wZXJ0eSB7eWF1emwuRW50cnl9IGVudHJ5IFRoZSBhY3R1YWwgZW50cnkgaW5zdGFuY2VcbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb259IGV4dHJhY3RFbnRyeVRvIEFuIGFzeW5jIGZ1bmN0aW9uLCB3aGljaCBhY2NlcHRzIG9uZSBwYXJhbWV0ZXIuXG4gKiBUaGlzIHBhcmFtZXRlciBjb250YWlucyB0aGUgZGVzdGluYXRpb24gZm9sZGVyIHBhdGggdG8gd2hpY2ggdGhpcyBmdW5jdGlvbiBpcyBnb2luZyB0byBleHRyYWN0IHRoZSBlbnRyeS5cbiAqL1xuXG4vKipcbiAqIEdldCBlbnRyaWVzIGZvciBhIHppcCBmb2xkZXJcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gemlwRmlsZVBhdGggVGhlIGZ1bGwgcGF0aCB0byB0aGUgc291cmNlIFpJUCBmaWxlXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBvbkVudHJ5IENhbGxiYWNrIHdoZW4gZW50cnkgaXMgcmVhZC5cbiAqIFRoZSBjYWxsYmFjayBpcyBleHBlY3RlZCB0byBhY2NlcHQgb25lIGFyZ3VtZW50IG9mIFppcEVudHJ5IHR5cGUuXG4gKiBUaGUgaXRlcmF0aW9uIHRocm91Z2ggdGhlIHNvdXJjZSB6aXAgZmlsZSB3aWxsIGJpIHRlcm1pbmF0ZWQgYXMgc29vbiBhc1xuICogdGhlIHJlc3VsdCBvZiB0aGlzIGZ1bmN0aW9uIGVxdWFscyB0byBgZmFsc2VgLlxuICovXG5hc3luYyBmdW5jdGlvbiByZWFkRW50cmllcyh6aXBGaWxlUGF0aCwgb25FbnRyeSkge1xuICAvLyBPcGVuIGEgemlwIGZpbGUgYW5kIHN0YXJ0IHJlYWRpbmcgZW50cmllc1xuICBjb25zdCB6aXBmaWxlID0gYXdhaXQgb3BlblppcCh6aXBGaWxlUGF0aCwge2xhenlFbnRyaWVzOiB0cnVlfSk7XG4gIGNvbnN0IHppcFJlYWRTdHJlYW1Qcm9taXNlID0gbmV3IEIoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHppcGZpbGUub25jZSgnZW5kJywgcmVzb2x2ZSk7XG4gICAgemlwZmlsZS5vbmNlKCdlcnJvcicsIHJlamVjdCk7XG5cbiAgICAvLyBPbiBlYWNoIGVudHJ5LCBjYWxsICdvbkVudHJ5JyBhbmQgdGhlbiByZWFkIHRoZSBuZXh0IGVudHJ5XG4gICAgemlwZmlsZS5vbignZW50cnknLCBhc3luYyAoZW50cnkpID0+IHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IG9uRW50cnkoe1xuICAgICAgICBlbnRyeSxcbiAgICAgICAgZXh0cmFjdEVudHJ5VG86IGFzeW5jIChkZXN0RGlyKSA9PiBhd2FpdCBfZXh0cmFjdEVudHJ5VG8oemlwZmlsZSwgZW50cnksIGRlc3REaXIpLFxuICAgICAgfSk7XG4gICAgICBpZiAocmVzID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm4gemlwZmlsZS5lbWl0KCdlbmQnKTtcbiAgICAgIH1cbiAgICAgIHppcGZpbGUucmVhZEVudHJ5KCk7XG4gICAgfSk7XG4gIH0pO1xuICB6aXBmaWxlLnJlYWRFbnRyeSgpO1xuXG4gIC8vIFdhaXQgZm9yIHRoZSBlbnRyaWVzIHRvIGZpbmlzaCBiZWluZyBpdGVyYXRlZCB0aHJvdWdoXG4gIHJldHVybiBhd2FpdCB6aXBSZWFkU3RyZWFtUHJvbWlzZTtcbn1cblxuLyoqXG4gKiBAdHlwZWRlZiBaaXBPcHRpb25zXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGVuY29kZVRvQmFzZTY0IFtmYWxzZV0gV2hldGhlciB0byBlbmNvZGVcbiAqIHRoZSByZXN1bHRpbmcgYXJjaGl2ZSB0byBhIGJhc2U2NC1lbmNvZGVkIHN0cmluZ1xuICogQHByb3BlcnR5IHtib29sZWFufSBpc01ldGVyZWQgW3RydWVdIFdoZXRoZXIgdG8gbG9nIHRoZSBhY3R1YWxcbiAqIGFyY2hpdmVyIHBlcmZvcm1hbmNlXG4gKiBAcHJvcGVydHkge251bWJlcn0gbWF4U2l6ZSBbMTA3Mzc0MTgyNF0gVGhlIG1heGltdW0gc2l6ZSBvZlxuICogdGhlIHJlc3VsdGluZyBhcmNoaXZlIGluIGJ5dGVzLiBUaGlzIGlzIHNldCB0byAxR0IgYnkgZGVmYXVsdCwgYmVjYXVzZVxuICogQXBwaXVtIGxpbWl0cyB0aGUgbWF4aW11bSBIVFRQIGJvZHkgc2l6ZSB0byAxR0IuIEFsc28sIHRoZSBOb2RlSlMgaGVhcFxuICogc2l6ZSBtdXN0IGJlIGVub3VnaCB0byBrZWVwIHRoZSByZXN1bHRpbmcgb2JqZWN0ICh1c3VhbGx5IHRoaXMgc2l6ZSBpc1xuICogbGltaXRlZCB0byAxLjQgR0IpXG4gKiBAcHJvcGVydHkge251bWJlcn0gbGV2ZWwgWzldIFRoZSBjb21wcmVzc2lvbiBsZXZlbC4gVGhlIG1heGltdW1cbiAqIGxldmVsIGlzIDkgKHRoZSBiZXN0IGNvbXByZXNzaW9uLCB3b3JzdCBwZXJmb3JtYW5jZSkuIFRoZSBtaW5pbXVtXG4gKiBjb21wcmVzc2lvbiBsZXZlbCBpcyAwIChubyBjb21wcmVzc2lvbikuXG4gKi9cblxuLyoqXG4gKiBDb252ZXJ0cyBjb250ZW50cyBvZiBsb2NhbCBkaXJlY3RvcnkgdG8gYW4gaW4tbWVtb3J5IC56aXAgYnVmZmVyXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHNyY1BhdGggVGhlIGZ1bGwgcGF0aCB0byB0aGUgZm9sZGVyIG9yIGZpbGUgYmVpbmcgemlwcGVkXG4gKiBAcGFyYW0ge1ppcE9wdGlvbnN9IG9wdHMgWmlwcGluZyBvcHRpb25zXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxCdWZmZXI+fSBaaXBwZWQgKGFuZCBlbmNvZGVkIGlmIGBlbmNvZGVUb0Jhc2U2NGAgaXMgdHJ1dGh5KVxuICogY29udGVudCBvZiB0aGUgc291cmNlIHBhdGggYXMgbWVtb3J5IGJ1ZmZlclxuICogQHRocm93cyB7RXJyb3J9IGlmIHRoZXJlIHdhcyBhbiBlcnJvciB3aGlsZSByZWFkaW5nIHRoZSBzb3VyY2VcbiAqIG9yIHRoZSBzb3VyY2UgaXMgdG9vIGJpZ1xuICovXG5hc3luYyBmdW5jdGlvbiB0b0luTWVtb3J5WmlwKHNyY1BhdGgsIG9wdHMgPSAvKiogQHR5cGUge1ppcE9wdGlvbnN9ICovICh7fSkpIHtcbiAgaWYgKCEoYXdhaXQgZnMuZXhpc3RzKHNyY1BhdGgpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgTm8gc3VjaCBmaWxlIG9yIGZvbGRlcjogJHtzcmNQYXRofWApO1xuICB9XG5cbiAgY29uc3Qge2lzTWV0ZXJlZCA9IHRydWUsIGVuY29kZVRvQmFzZTY0ID0gZmFsc2UsIG1heFNpemUgPSAxICogR2lCLCBsZXZlbCA9IDl9ID0gb3B0cztcbiAgY29uc3QgcmVzdWx0QnVmZmVycyA9IFtdO1xuICBsZXQgcmVzdWx0QnVmZmVyc1NpemUgPSAwO1xuICAvLyBDcmVhdGUgYSB3cml0YWJsZSBzdHJlYW0gdGhhdCB6aXAgYnVmZmVycyB3aWxsIGJlIHN0cmVhbWVkIHRvXG4gIGNvbnN0IHJlc3VsdFdyaXRlU3RyZWFtID0gbmV3IHN0cmVhbS5Xcml0YWJsZSh7XG4gICAgd3JpdGU6IChidWZmZXIsIGVuY29kaW5nLCBuZXh0KSA9PiB7XG4gICAgICByZXN1bHRCdWZmZXJzLnB1c2goYnVmZmVyKTtcbiAgICAgIHJlc3VsdEJ1ZmZlcnNTaXplICs9IGJ1ZmZlci5sZW5ndGg7XG4gICAgICBpZiAobWF4U2l6ZSA+IDAgJiYgcmVzdWx0QnVmZmVyc1NpemUgPiBtYXhTaXplKSB7XG4gICAgICAgIHJlc3VsdFdyaXRlU3RyZWFtLmVtaXQoXG4gICAgICAgICAgJ2Vycm9yJyxcbiAgICAgICAgICBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgVGhlIHNpemUgb2YgdGhlIHJlc3VsdGluZyBgICtcbiAgICAgICAgICAgICAgYGFyY2hpdmUgbXVzdCBub3QgYmUgZ3JlYXRlciB0aGFuICR7dG9SZWFkYWJsZVNpemVTdHJpbmcobWF4U2l6ZSl9YFxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIG5leHQoKTtcbiAgICB9LFxuICB9KTtcblxuICAvLyBaaXAgJ3NyY0RpcicgYW5kIHN0cmVhbSBpdCB0byB0aGUgYWJvdmUgd3JpdGFibGUgc3RyZWFtXG4gIGNvbnN0IGFyY2hpdmUgPSBhcmNoaXZlcignemlwJywge1xuICAgIHpsaWI6IHtsZXZlbH0sXG4gIH0pO1xuICBsZXQgc3JjU2l6ZSA9IG51bGw7XG4gIGNvbnN0IGJhc2U2NEVuY29kZXJTdHJlYW0gPSBlbmNvZGVUb0Jhc2U2NCA/IG5ldyBCYXNlNjRFbmNvZGUoKSA6IG51bGw7XG4gIGNvbnN0IHJlc3VsdFdyaXRlU3RyZWFtUHJvbWlzZSA9IG5ldyBCKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICByZXN1bHRXcml0ZVN0cmVhbS5vbmNlKCdlcnJvcicsIChlKSA9PiB7XG4gICAgICBpZiAoYmFzZTY0RW5jb2RlclN0cmVhbSkge1xuICAgICAgICBhcmNoaXZlLnVucGlwZShiYXNlNjRFbmNvZGVyU3RyZWFtKTtcbiAgICAgICAgYmFzZTY0RW5jb2RlclN0cmVhbS51bnBpcGUocmVzdWx0V3JpdGVTdHJlYW0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXJjaGl2ZS51bnBpcGUocmVzdWx0V3JpdGVTdHJlYW0pO1xuICAgICAgfVxuICAgICAgYXJjaGl2ZS5hYm9ydCgpO1xuICAgICAgYXJjaGl2ZS5kZXN0cm95KCk7XG4gICAgICByZWplY3QoZSk7XG4gICAgfSk7XG4gICAgcmVzdWx0V3JpdGVTdHJlYW0ub25jZSgnZmluaXNoJywgKCkgPT4ge1xuICAgICAgc3JjU2l6ZSA9IGFyY2hpdmUucG9pbnRlcigpO1xuICAgICAgcmVzb2x2ZSgpO1xuICAgIH0pO1xuICB9KTtcbiAgY29uc3QgYXJjaGl2ZVN0cmVhbVByb21pc2UgPSBuZXcgQigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgYXJjaGl2ZS5vbmNlKCdmaW5pc2gnLCByZXNvbHZlKTtcbiAgICBhcmNoaXZlLm9uY2UoJ2Vycm9yJywgKGUpID0+IHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBhcmNoaXZlICcke3NyY1BhdGh9JzogJHtlLm1lc3NhZ2V9YCkpKTtcbiAgfSk7XG4gIGNvbnN0IHRpbWVyID0gaXNNZXRlcmVkID8gbmV3IFRpbWVyKCkuc3RhcnQoKSA6IG51bGw7XG4gIGlmICgoYXdhaXQgZnMuc3RhdChzcmNQYXRoKSkuaXNEaXJlY3RvcnkoKSkge1xuICAgIGFyY2hpdmUuZGlyZWN0b3J5KHNyY1BhdGgsIGZhbHNlKTtcbiAgfSBlbHNlIHtcbiAgICBhcmNoaXZlLmZpbGUoc3JjUGF0aCwge1xuICAgICAgbmFtZTogcGF0aC5iYXNlbmFtZShzcmNQYXRoKSxcbiAgICB9KTtcbiAgfVxuICBpZiAoYmFzZTY0RW5jb2RlclN0cmVhbSkge1xuICAgIGFyY2hpdmUucGlwZShiYXNlNjRFbmNvZGVyU3RyZWFtKTtcbiAgICBiYXNlNjRFbmNvZGVyU3RyZWFtLnBpcGUocmVzdWx0V3JpdGVTdHJlYW0pO1xuICB9IGVsc2Uge1xuICAgIGFyY2hpdmUucGlwZShyZXN1bHRXcml0ZVN0cmVhbSk7XG4gIH1cbiAgYXJjaGl2ZS5maW5hbGl6ZSgpO1xuXG4gIC8vIFdhaXQgZm9yIHRoZSBzdHJlYW1zIHRvIGZpbmlzaFxuICBhd2FpdCBCLmFsbChbYXJjaGl2ZVN0cmVhbVByb21pc2UsIHJlc3VsdFdyaXRlU3RyZWFtUHJvbWlzZV0pO1xuXG4gIGlmICh0aW1lcikge1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGBaaXBwZWQgJHtlbmNvZGVUb0Jhc2U2NCA/ICdhbmQgYmFzZTY0LWVuY29kZWQgJyA6ICcnfWAgK1xuICAgICAgICBgJyR7cGF0aC5iYXNlbmFtZShzcmNQYXRoKX0nIGAgK1xuICAgICAgICAoc3JjU2l6ZSA/IGAoJHt0b1JlYWRhYmxlU2l6ZVN0cmluZyhzcmNTaXplKX0pIGAgOiAnJykgK1xuICAgICAgICBgaW4gJHt0aW1lci5nZXREdXJhdGlvbigpLmFzU2Vjb25kcy50b0ZpeGVkKDMpfXMgYCArXG4gICAgICAgIGAoY29tcHJlc3Npb24gbGV2ZWw6ICR7bGV2ZWx9KWBcbiAgICApO1xuICB9XG4gIC8vIFJldHVybiB0aGUgYXJyYXkgb2YgemlwIGJ1ZmZlcnMgY29uY2F0ZW5hdGVkIGludG8gb25lIGJ1ZmZlclxuICByZXR1cm4gQnVmZmVyLmNvbmNhdChyZXN1bHRCdWZmZXJzKTtcbn1cblxuLyoqXG4gKiBWZXJpZmllcyB3aGV0aGVyIHRoZSBnaXZlbiBmaWxlIGlzIGEgdmFsaWQgWklQIGFyY2hpdmVcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZVBhdGggLSBGdWxsIHBhdGggdG8gdGhlIGZpbGVcbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgZmlsZSBkb2VzIG5vdCBleGlzdCBvciBpcyBub3QgYSB2YWxpZCBaSVAgYXJjaGl2ZVxuICovXG5hc3luYyBmdW5jdGlvbiBhc3NlcnRWYWxpZFppcChmaWxlUGF0aCkge1xuICBpZiAoIShhd2FpdCBmcy5leGlzdHMoZmlsZVBhdGgpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVGhlIGZpbGUgYXQgJyR7ZmlsZVBhdGh9JyBkb2VzIG5vdCBleGlzdGApO1xuICB9XG5cbiAgY29uc3Qge3NpemV9ID0gYXdhaXQgZnMuc3RhdChmaWxlUGF0aCk7XG4gIGlmIChzaXplIDwgNCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVGhlIGZpbGUgYXQgJyR7ZmlsZVBhdGh9JyBpcyB0b28gc21hbGwgdG8gYmUgYSBaSVAgYXJjaGl2ZWApO1xuICB9XG4gIGNvbnN0IGZkID0gYXdhaXQgZnMub3BlbihmaWxlUGF0aCwgJ3InKTtcbiAgdHJ5IHtcbiAgICBjb25zdCBidWZmZXIgPSBCdWZmZXIuYWxsb2MoWklQX01BR0lDLmxlbmd0aCk7XG4gICAgYXdhaXQgZnMucmVhZChmZCwgYnVmZmVyLCAwLCBaSVBfTUFHSUMubGVuZ3RoLCAwKTtcbiAgICBjb25zdCBzaWduYXR1cmUgPSBidWZmZXIudG9TdHJpbmcoJ2FzY2lpJyk7XG4gICAgaWYgKHNpZ25hdHVyZSAhPT0gWklQX01BR0lDKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBUaGUgZmlsZSBzaWduYXR1cmUgJyR7c2lnbmF0dXJlfScgb2YgJyR7ZmlsZVBhdGh9JyBgICtcbiAgICAgICAgICBgaXMgbm90IGVxdWFsIHRvIHRoZSBleHBlY3RlZCBaSVAgYXJjaGl2ZSBzaWduYXR1cmUgJyR7WklQX01BR0lDfSdgXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCBmcy5jbG9zZShmZCk7XG4gIH1cbn1cblxuLyoqXG4gKiBAdHlwZWRlZiBaaXBDb21wcmVzc2lvbk9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBsZXZlbCBbOV0gLSBDb21wcmVzc2lvbiBsZXZlbCBpbiByYW5nZSAwLi45XG4gKiAoZ3JlYXRlciBudW1iZXJzIG1lYW4gYmV0dGVyIGNvbXByZXNzaW9uLCBidXQgbG9uZ2VyIHByb2Nlc3NpbmcgdGltZSlcbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIFppcFNvdXJjZU9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBwYXR0ZXJuIFsnKipcXC8qJ10gLSBHTE9CIHBhdHRlcm4gZm9yIGNvbXByZXNzaW9uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gY3dkIC0gVGhlIHNvdXJjZSByb290IGZvbGRlciAodGhlIHBhcmVudCBmb2xkZXIgb2ZcbiAqIHRoZSBkZXN0aW5hdGlvbiBmaWxlIGJ5IGRlZmF1bHQpXG4gKiBAcHJvcGVydHkge3N0cmluZ1tdfSBbaWdub3JlXSAtIFRoZSBsaXN0IG9mIGlnbm9yZWQgcGF0dGVybnNcbiAqL1xuXG4vKipcbiAqIENyZWF0ZXMgYW4gYXJjaGl2ZSBiYXNlZCBvbiB0aGUgZ2l2ZW4gZ2xvYiBwYXR0ZXJuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGRzdFBhdGggLSBUaGUgcmVzdWx0aW5nIGFyY2hpdmUgcGF0aFxuICogQHBhcmFtIHtaaXBTb3VyY2VPcHRpb25zfSBzcmMgLSBTb3VyY2Ugb3B0aW9uc1xuICogQHBhcmFtIHtaaXBDb21wcmVzc2lvbk9wdGlvbnN9IG9wdHMgLSBDb21wcmVzc2lvbiBvcHRpb25zXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlcmUgd2FzIGFuIGVycm9yIHdoaWxlIGNyZWF0aW5nIHRoZSBhcmNoaXZlXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHRvQXJjaGl2ZShcbiAgZHN0UGF0aCxcbiAgc3JjID0gLyoqIEB0eXBlIHtaaXBTb3VyY2VPcHRpb25zfSAqLyAoe30pLFxuICBvcHRzID0gLyoqIEB0eXBlIHtaaXBDb21wcmVzc2lvbk9wdGlvbnN9ICovICh7fSlcbikge1xuICBjb25zdCB7bGV2ZWwgPSA5fSA9IG9wdHM7XG4gIGNvbnN0IHtwYXR0ZXJuID0gJyoqLyonLCBjd2QgPSBwYXRoLmRpcm5hbWUoZHN0UGF0aCksIGlnbm9yZSA9IFtdfSA9IHNyYztcbiAgY29uc3QgYXJjaGl2ZSA9IGFyY2hpdmVyKCd6aXAnLCB7emxpYjoge2xldmVsfX0pO1xuICBjb25zdCBzdHJlYW0gPSBmcy5jcmVhdGVXcml0ZVN0cmVhbShkc3RQYXRoKTtcbiAgcmV0dXJuIGF3YWl0IG5ldyBCKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBhcmNoaXZlXG4gICAgICAuZ2xvYihwYXR0ZXJuLCB7XG4gICAgICAgIGN3ZCxcbiAgICAgICAgaWdub3JlLFxuICAgICAgfSlcbiAgICAgIC5vbignZXJyb3InLCByZWplY3QpXG4gICAgICAucGlwZShzdHJlYW0pO1xuICAgIHN0cmVhbVxuICAgICAgLm9uKCdlcnJvcicsIChlKSA9PiB7XG4gICAgICAgIGFyY2hpdmUudW5waXBlKHN0cmVhbSk7XG4gICAgICAgIGFyY2hpdmUuYWJvcnQoKTtcbiAgICAgICAgYXJjaGl2ZS5kZXN0cm95KCk7XG4gICAgICAgIHJlamVjdChlKTtcbiAgICAgIH0pXG4gICAgICAub24oJ2ZpbmlzaCcsIHJlc29sdmUpO1xuICAgIGFyY2hpdmUuZmluYWxpemUoKTtcbiAgfSk7XG59XG5cbi8qKlxuICogRmluZHMgYW5kIG1lbW9pemVzIHRoZSBmdWxsIHBhdGggdG8gdGhlIGdpdmVuIGV4ZWN1dGFibGUuXG4gKiBSZWplY3RzIGlmIGl0IGlzIG5vdCBmb3VuZC5cbiAqL1xuY29uc3QgZ2V0RXhlY3V0YWJsZVBhdGggPSBfLm1lbW9pemUoXG4gIC8qKlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSBGdWxsIFBhdGggdG8gdGhlIGV4ZWN1dGFibGVcbiAgICovXG4gIGFzeW5jIGZ1bmN0aW9uIGdldEV4ZWN1dGFibGVQYXRoKGJpbmFyeU5hbWUpIHtcbiAgICBjb25zdCBmdWxsUGF0aCA9IGF3YWl0IGZzLndoaWNoKGJpbmFyeU5hbWUpO1xuICAgIGxvZy5kZWJ1ZyhgRm91bmQgJyR7YmluYXJ5TmFtZX0nIGF0ICcke2Z1bGxQYXRofSdgKTtcbiAgICByZXR1cm4gZnVsbFBhdGg7XG4gIH1cbik7XG5cbmV4cG9ydCB7ZXh0cmFjdEFsbFRvLCByZWFkRW50cmllcywgdG9Jbk1lbW9yeVppcCwgX2V4dHJhY3RFbnRyeVRvLCBhc3NlcnRWYWxpZFppcCwgdG9BcmNoaXZlfTtcbmV4cG9ydCBkZWZhdWx0IHtcbiAgZXh0cmFjdEFsbFRvLFxuICByZWFkRW50cmllcyxcbiAgdG9Jbk1lbW9yeVppcCxcbiAgYXNzZXJ0VmFsaWRaaXAsXG4gIHRvQXJjaGl2ZSxcbn07XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOzs7O0FBS0EsTUFBTUEsT0FBTyxHQUFHQyxpQkFBQSxDQUFFQyxTQUFGLENBQVlDLGNBQUEsQ0FBTUMsSUFBbEIsQ0FBaEI7O0FBSUEsTUFBTUMsUUFBUSxHQUFHSixpQkFBQSxDQUFFQyxTQUFGLENBQVlJLGVBQUEsQ0FBT0QsUUFBbkIsQ0FBakI7O0FBQ0EsTUFBTUUsU0FBUyxHQUFHLElBQWxCO0FBQ0EsTUFBTUMsSUFBSSxHQUFHLEtBQWI7QUFDQSxNQUFNQyxLQUFLLEdBQUcsS0FBZDtBQUNBLE1BQU1DLEtBQUssR0FBRyxLQUFkOztBQUdBLE1BQU1DLFlBQU4sQ0FBbUI7RUFFakJDLE9BQU87O0VBRVBDLFdBQVcsQ0FBQ0MsVUFBRCxFQUFhQyxJQUFJLEdBQUcsRUFBcEIsRUFBd0I7SUFDakMsS0FBS0MsT0FBTCxHQUFlRixVQUFmO0lBQ0EsS0FBS0MsSUFBTCxHQUFZQSxJQUFaO0lBQ0EsS0FBS0UsUUFBTCxHQUFnQixLQUFoQjtFQUNEOztFQUVEQyxlQUFlLENBQUNDLEtBQUQsRUFBUTtJQUNyQixPQUFPQyxlQUFBLENBQUVDLFFBQUYsQ0FBV0YsS0FBSyxDQUFDRyxRQUFqQixJQUNISCxLQUFLLENBQUNH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
507
+ //# sourceMappingURL=zip.js.map