@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/net.js CHANGED
@@ -1,272 +1,296 @@
1
1
  "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.downloadFile = downloadFile;
7
- exports.uploadFile = uploadFile;
8
-
9
- require("source-map-support/register");
10
-
11
- var _lodash = _interopRequireDefault(require("lodash"));
12
-
13
- var _fs = _interopRequireDefault(require("./fs"));
14
-
15
- var _bluebird = _interopRequireDefault(require("bluebird"));
16
-
17
- var _util = require("./util");
18
-
19
- var _logger = _interopRequireDefault(require("./logger"));
20
-
21
- var _jsftp = _interopRequireDefault(require("jsftp"));
22
-
23
- var _timing = _interopRequireDefault(require("./timing"));
24
-
25
- var _axios = _interopRequireDefault(require("axios"));
26
-
27
- var _formData = _interopRequireDefault(require("form-data"));
28
-
29
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
30
-
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.downloadFile = exports.uploadFile = void 0;
7
+ const lodash_1 = __importDefault(require("lodash"));
8
+ const fs_1 = __importDefault(require("./fs"));
9
+ const bluebird_1 = __importDefault(require("bluebird"));
10
+ const util_1 = require("./util");
11
+ const logger_1 = __importDefault(require("./logger"));
12
+ const jsftp_1 = __importDefault(require("jsftp"));
13
+ const timing_1 = __importDefault(require("./timing"));
14
+ const axios_1 = __importDefault(require("axios"));
15
+ const form_data_1 = __importDefault(require("form-data"));
31
16
  const DEFAULT_TIMEOUT_MS = 4 * 60 * 1000;
32
-
17
+ /**
18
+ * Type guard for param to {@linkcode toAxiosAuth}
19
+ * @param {any} value
20
+ * @returns {value is AuthCredentials | import('axios').AxiosBasicCredentials}
21
+ */
22
+ function isAxiosAuth(value) {
23
+ return lodash_1.default.isPlainObject(value);
24
+ }
25
+ /**
26
+ * Converts {@linkcode AuthCredentials} to credentials understood by {@linkcode axios}.
27
+ * @param {AuthCredentials | import('axios').AxiosBasicCredentials} [auth]
28
+ * @returns {import('axios').AxiosBasicCredentials?}
29
+ */
33
30
  function toAxiosAuth(auth) {
34
- if (!_lodash.default.isPlainObject(auth)) {
35
- return null;
36
- }
37
-
38
- const axiosAuth = {
39
- username: _lodash.default.get(auth, 'username', _lodash.default.get(auth, 'user')),
40
- password: _lodash.default.get(auth, 'password', _lodash.default.get(auth, 'pass'))
41
- };
42
- return axiosAuth.username && axiosAuth.password ? axiosAuth : null;
31
+ if (!isAxiosAuth(auth)) {
32
+ return null;
33
+ }
34
+ const axiosAuth = {
35
+ username: 'username' in auth ? auth.username : auth.user,
36
+ password: 'password' in auth ? auth.password : auth.pass,
37
+ };
38
+ return axiosAuth.username && axiosAuth.password ? axiosAuth : null;
43
39
  }
44
-
45
- async function uploadFileToHttp(localFileStream, parsedUri, uploadOptions = {}) {
46
- const {
47
- method = 'POST',
48
- timeout = DEFAULT_TIMEOUT_MS,
49
- headers,
50
- auth,
51
- fileFieldName = 'file',
52
- formFields
53
- } = uploadOptions;
54
- const {
55
- href
56
- } = parsedUri;
57
- const requestOpts = {
58
- url: href,
59
- method,
60
- timeout,
61
- maxContentLength: Infinity,
62
- maxBodyLength: Infinity
63
- };
64
- const axiosAuth = toAxiosAuth(auth);
65
-
66
- if (axiosAuth) {
67
- requestOpts.auth = axiosAuth;
68
- }
69
-
70
- if (fileFieldName) {
71
- const form = new _formData.default();
72
- form.append(fileFieldName, localFileStream);
73
-
74
- if (formFields) {
75
- let pairs = [];
76
-
77
- if (_lodash.default.isArray(formFields)) {
78
- pairs = formFields;
79
- } else if (_lodash.default.isPlainObject(formFields)) {
80
- pairs = _lodash.default.toPairs(formFields);
81
- }
82
-
83
- for (const [key, value] of pairs) {
84
- if (_lodash.default.toLower(key) !== _lodash.default.toLower(fileFieldName)) {
85
- form.append(key, value);
40
+ /**
41
+ * @param {NodeJS.ReadableStream} localFileStream
42
+ * @param {URL} parsedUri
43
+ * @param {HttpUploadOptions & NetOptions} [uploadOptions]
44
+ */
45
+ async function uploadFileToHttp(localFileStream, parsedUri, uploadOptions = /** @type {HttpUploadOptions & NetOptions} */ ({})) {
46
+ const { method = 'POST', timeout = DEFAULT_TIMEOUT_MS, headers, auth, fileFieldName = 'file', formFields, } = uploadOptions;
47
+ const { href } = parsedUri;
48
+ /** @type {import('axios').AxiosRequestConfig} */
49
+ const requestOpts = {
50
+ url: href,
51
+ method,
52
+ timeout,
53
+ maxContentLength: Infinity,
54
+ maxBodyLength: Infinity,
55
+ };
56
+ const axiosAuth = toAxiosAuth(auth);
57
+ if (axiosAuth) {
58
+ requestOpts.auth = axiosAuth;
59
+ }
60
+ if (fileFieldName) {
61
+ const form = new form_data_1.default();
62
+ form.append(fileFieldName, localFileStream);
63
+ if (formFields) {
64
+ let pairs = [];
65
+ if (lodash_1.default.isArray(formFields)) {
66
+ pairs = formFields;
67
+ }
68
+ else if (lodash_1.default.isPlainObject(formFields)) {
69
+ pairs = lodash_1.default.toPairs(formFields);
70
+ }
71
+ for (const [key, value] of pairs) {
72
+ if (lodash_1.default.toLower(key) !== lodash_1.default.toLower(fileFieldName)) {
73
+ form.append(key, value);
74
+ }
75
+ }
86
76
  }
87
- }
77
+ requestOpts.headers = {
78
+ ...(lodash_1.default.isPlainObject(headers) ? headers : {}),
79
+ ...form.getHeaders(),
80
+ };
81
+ requestOpts.data = form;
88
82
  }
89
-
90
- requestOpts.headers = { ...(_lodash.default.isPlainObject(headers) ? headers : {}),
91
- ...form.getHeaders()
92
- };
93
- requestOpts.data = form;
94
- } else {
95
- if (_lodash.default.isPlainObject(headers)) {
96
- requestOpts.headers = headers;
83
+ else {
84
+ if (lodash_1.default.isPlainObject(headers)) {
85
+ requestOpts.headers = headers;
86
+ }
87
+ requestOpts.data = localFileStream;
97
88
  }
98
-
99
- requestOpts.data = localFileStream;
100
- }
101
-
102
- _logger.default.debug(`Performing ${method} to ${href} with options (excluding data): ` + JSON.stringify(_lodash.default.omit(requestOpts, ['data'])));
103
-
104
- const {
105
- status,
106
- statusText
107
- } = await (0, _axios.default)(requestOpts);
108
-
109
- _logger.default.info(`Server response: ${status} ${statusText}`);
89
+ logger_1.default.debug(`Performing ${method} to ${href} with options (excluding data): ` +
90
+ JSON.stringify(lodash_1.default.omit(requestOpts, ['data'])));
91
+ const { status, statusText } = await (0, axios_1.default)(requestOpts);
92
+ logger_1.default.info(`Server response: ${status} ${statusText}`);
110
93
  }
111
-
112
- async function uploadFileToFtp(localFileStream, parsedUri, uploadOptions = {}) {
113
- const {
114
- auth
115
- } = uploadOptions;
116
- const {
117
- hostname,
118
- port,
119
- protocol,
120
- pathname
121
- } = parsedUri;
122
- const ftpOpts = {
123
- host: hostname,
124
- port: !_lodash.default.isUndefined(port) ? _lodash.default.parseInt(port) : 21
125
- };
126
-
127
- if (auth !== null && auth !== void 0 && auth.user && auth !== null && auth !== void 0 && auth.pass) {
128
- ftpOpts.user = auth.user;
129
- ftpOpts.pass = auth.pass;
130
- }
131
-
132
- _logger.default.debug(`${protocol} upload options: ${JSON.stringify(ftpOpts)}`);
133
-
134
- return await new _bluebird.default((resolve, reject) => {
135
- new _jsftp.default(ftpOpts).put(localFileStream, pathname, err => {
136
- if (err) {
137
- reject(err);
138
- } else {
139
- resolve();
140
- }
94
+ /**
95
+ * @param {string | Buffer | NodeJS.ReadableStream} localFileStream
96
+ * @param {URL} parsedUri
97
+ * @param {NotHttpUploadOptions & NetOptions} [uploadOptions]
98
+ */
99
+ async function uploadFileToFtp(localFileStream, parsedUri, uploadOptions = /** @type {NotHttpUploadOptions & NetOptions} */ ({})) {
100
+ const { auth } = uploadOptions;
101
+ const { hostname, port, protocol, pathname } = parsedUri;
102
+ const ftpOpts = {
103
+ host: hostname,
104
+ port: !lodash_1.default.isUndefined(port) ? lodash_1.default.parseInt(port) : 21,
105
+ };
106
+ if (auth?.user && auth?.pass) {
107
+ ftpOpts.user = auth.user;
108
+ ftpOpts.pass = auth.pass;
109
+ }
110
+ logger_1.default.debug(`${protocol} upload options: ${JSON.stringify(ftpOpts)}`);
111
+ return await new bluebird_1.default((resolve, reject) => {
112
+ new jsftp_1.default(ftpOpts).put(localFileStream, pathname, (err) => {
113
+ if (err) {
114
+ reject(err);
115
+ }
116
+ else {
117
+ resolve();
118
+ }
119
+ });
141
120
  });
142
- });
143
121
  }
144
-
122
+ /**
123
+ * Returns `true` if params are valid for {@linkcode uploadFileToHttp}.
124
+ * @param {any} opts
125
+ * @param {URL} url
126
+ * @returns {opts is HttpUploadOptions & NetOptions}
127
+ */
145
128
  function isHttpUploadOptions(opts, url) {
146
- try {
147
- const {
148
- protocol
149
- } = new URL(url);
150
- return protocol === 'http:' || protocol === 'https:';
151
- } catch {
152
- return false;
153
- }
129
+ try {
130
+ const { protocol } = url;
131
+ return protocol === 'http:' || protocol === 'https:';
132
+ }
133
+ catch {
134
+ return false;
135
+ }
154
136
  }
155
-
137
+ /**
138
+ * Returns `true` if params are valid for {@linkcode uploadFileToFtp}.
139
+ * @param {any} opts
140
+ * @param {URL} url
141
+ * @returns {opts is NotHttpUploadOptions & NetOptions}
142
+ */
156
143
  function isNotHttpUploadOptions(opts, url) {
157
- try {
158
- const {
159
- protocol
160
- } = new URL(url);
161
- return protocol === 'ftp:';
162
- } catch {
163
- return false;
164
- }
144
+ try {
145
+ const { protocol } = url;
146
+ return protocol === 'ftp:';
147
+ }
148
+ catch {
149
+ return false;
150
+ }
165
151
  }
166
-
167
- async function uploadFile(localPath, remoteUri, uploadOptions = {}) {
168
- if (!(await _fs.default.exists(localPath))) {
169
- throw new Error(`'${localPath}' does not exists or is not accessible`);
170
- }
171
-
172
- const {
173
- isMetered = true
174
- } = uploadOptions;
175
- const url = new URL(remoteUri);
176
- const {
177
- size
178
- } = await _fs.default.stat(localPath);
179
-
180
- if (isMetered) {
181
- _logger.default.info(`Uploading '${localPath}' of ${(0, _util.toReadableSizeString)(size)} size to '${remoteUri}'`);
182
- }
183
-
184
- const timer = new _timing.default().start();
185
-
186
- if (isHttpUploadOptions(uploadOptions, url)) {
187
- if (!uploadOptions.fileFieldName) {
188
- uploadOptions.headers = { ...(_lodash.default.isPlainObject(uploadOptions.headers) ? uploadOptions.headers : {}),
189
- 'Content-Length': size
190
- };
152
+ /**
153
+ * Uploads the given file to a remote location. HTTP(S) and FTP
154
+ * protocols are supported.
155
+ *
156
+ * @param {string} localPath - The path to a file on the local storage.
157
+ * @param {string} remoteUri - The remote URI to upload the file to.
158
+ * @param {(HttpUploadOptions|NotHttpUploadOptions) & NetOptions} [uploadOptions]
159
+ * @returns {Promise<void>}
160
+ */
161
+ async function uploadFile(localPath, remoteUri, uploadOptions = /** @type {(HttpUploadOptions|NotHttpUploadOptions) & NetOptions} */ ({})) {
162
+ if (!(await fs_1.default.exists(localPath))) {
163
+ throw new Error(`'${localPath}' does not exists or is not accessible`);
164
+ }
165
+ const { isMetered = true } = uploadOptions;
166
+ const url = new URL(remoteUri);
167
+ const { size } = await fs_1.default.stat(localPath);
168
+ if (isMetered) {
169
+ logger_1.default.info(`Uploading '${localPath}' of ${(0, util_1.toReadableSizeString)(size)} size to '${remoteUri}'`);
170
+ }
171
+ const timer = new timing_1.default().start();
172
+ if (isHttpUploadOptions(uploadOptions, url)) {
173
+ if (!uploadOptions.fileFieldName) {
174
+ uploadOptions.headers = {
175
+ ...(lodash_1.default.isPlainObject(uploadOptions.headers) ? uploadOptions.headers : {}),
176
+ 'Content-Length': size,
177
+ };
178
+ }
179
+ await uploadFileToHttp(fs_1.default.createReadStream(localPath), url, uploadOptions);
180
+ }
181
+ else if (isNotHttpUploadOptions(uploadOptions, url)) {
182
+ await uploadFileToFtp(fs_1.default.createReadStream(localPath), url, uploadOptions);
183
+ }
184
+ else {
185
+ throw new Error(`Cannot upload the file at '${localPath}' to '${remoteUri}'. ` +
186
+ `Unsupported remote protocol '${url.protocol}'. ` +
187
+ `Only http/https and ftp/ftps protocols are supported.`);
188
+ }
189
+ if (isMetered) {
190
+ logger_1.default.info(`Uploaded '${localPath}' of ${(0, util_1.toReadableSizeString)(size)} size in ` +
191
+ `${timer.getDuration().asSeconds.toFixed(3)}s`);
191
192
  }
192
-
193
- await uploadFileToHttp(_fs.default.createReadStream(localPath), url, uploadOptions);
194
- } else if (isNotHttpUploadOptions(uploadOptions, url)) {
195
- await uploadFileToFtp(_fs.default.createReadStream(localPath), url, uploadOptions);
196
- } else {
197
- throw new Error(`Cannot upload the file at '${localPath}' to '${remoteUri}'. ` + `Unsupported remote protocol '${url.protocol}'. ` + `Only http/https and ftp/ftps protocols are supported.`);
198
- }
199
-
200
- if (isMetered) {
201
- _logger.default.info(`Uploaded '${localPath}' of ${(0, _util.toReadableSizeString)(size)} size in ` + `${timer.getDuration().asSeconds.toFixed(3)}s`);
202
- }
203
193
  }
204
-
205
- async function downloadFile(remoteUrl, dstPath, downloadOptions = {}) {
206
- const {
207
- isMetered = true,
208
- auth,
209
- timeout = DEFAULT_TIMEOUT_MS,
210
- headers
211
- } = downloadOptions;
212
- const requestOpts = {
213
- url: remoteUrl,
214
- responseType: 'stream',
215
- timeout
216
- };
217
- const axiosAuth = toAxiosAuth(auth);
218
-
219
- if (axiosAuth) {
220
- requestOpts.auth = axiosAuth;
221
- }
222
-
223
- if (_lodash.default.isPlainObject(headers)) {
224
- requestOpts.headers = headers;
225
- }
226
-
227
- const timer = new _timing.default().start();
228
- let responseLength;
229
-
230
- try {
231
- const writer = _fs.default.createWriteStream(dstPath);
232
-
233
- const {
234
- data: responseStream,
235
- headers: responseHeaders
236
- } = await (0, _axios.default)(requestOpts);
237
- responseLength = parseInt(responseHeaders['content-length'], 10);
238
- responseStream.pipe(writer);
239
- await new _bluebird.default((resolve, reject) => {
240
- responseStream.once('error', reject);
241
- writer.once('finish', resolve);
242
- writer.once('error', e => {
243
- responseStream.unpipe(writer);
244
- reject(e);
245
- });
246
- });
247
- } catch (err) {
248
- throw new Error(`Cannot download the file from ${remoteUrl}: ${err.message}`);
249
- }
250
-
251
- const {
252
- size
253
- } = await _fs.default.stat(dstPath);
254
-
255
- if (responseLength && size !== responseLength) {
256
- await _fs.default.rimraf(dstPath);
257
- throw new Error(`The size of the file downloaded from ${remoteUrl} (${size} bytes) ` + `differs from the one in Content-Length response header (${responseLength} bytes)`);
258
- }
259
-
260
- if (isMetered) {
261
- const secondsElapsed = timer.getDuration().asSeconds;
262
-
263
- _logger.default.debug(`${remoteUrl} (${(0, _util.toReadableSizeString)(size)}) ` + `has been downloaded to '${dstPath}' in ${secondsElapsed.toFixed(3)}s`);
264
-
265
- if (secondsElapsed >= 2) {
266
- const bytesPerSec = Math.floor(size / secondsElapsed);
267
-
268
- _logger.default.debug(`Approximate download speed: ${(0, _util.toReadableSizeString)(bytesPerSec)}/s`);
194
+ exports.uploadFile = uploadFile;
195
+ /**
196
+ * Downloads the given file via HTTP(S)
197
+ *
198
+ * @param {string} remoteUrl - The remote url
199
+ * @param {string} dstPath - The local path to download the file to
200
+ * @param {DownloadOptions & NetOptions} [downloadOptions]
201
+ * @throws {Error} If download operation fails
202
+ */
203
+ async function downloadFile(remoteUrl, dstPath, downloadOptions = /** @type {DownloadOptions & NetOptions} */ ({})) {
204
+ const { isMetered = true, auth, timeout = DEFAULT_TIMEOUT_MS, headers } = downloadOptions;
205
+ /**
206
+ * @type {import('axios').AxiosRequestConfig}
207
+ */
208
+ const requestOpts = {
209
+ url: remoteUrl,
210
+ responseType: 'stream',
211
+ timeout,
212
+ };
213
+ const axiosAuth = toAxiosAuth(auth);
214
+ if (axiosAuth) {
215
+ requestOpts.auth = axiosAuth;
216
+ }
217
+ if (lodash_1.default.isPlainObject(headers)) {
218
+ requestOpts.headers = headers;
219
+ }
220
+ const timer = new timing_1.default().start();
221
+ let responseLength;
222
+ try {
223
+ const writer = fs_1.default.createWriteStream(dstPath);
224
+ const { data: responseStream, headers: responseHeaders } = await (0, axios_1.default)(requestOpts);
225
+ responseLength = parseInt(responseHeaders['content-length'] || '0', 10);
226
+ responseStream.pipe(writer);
227
+ await new bluebird_1.default((resolve, reject) => {
228
+ responseStream.once('error', reject);
229
+ writer.once('finish', resolve);
230
+ writer.once('error', (e) => {
231
+ responseStream.unpipe(writer);
232
+ reject(e);
233
+ });
234
+ });
235
+ }
236
+ catch (err) {
237
+ throw new Error(`Cannot download the file from ${remoteUrl}: ${err.message}`);
238
+ }
239
+ const { size } = await fs_1.default.stat(dstPath);
240
+ if (responseLength && size !== responseLength) {
241
+ await fs_1.default.rimraf(dstPath);
242
+ throw new Error(`The size of the file downloaded from ${remoteUrl} (${size} bytes) ` +
243
+ `differs from the one in Content-Length response header (${responseLength} bytes)`);
244
+ }
245
+ if (isMetered) {
246
+ const secondsElapsed = timer.getDuration().asSeconds;
247
+ logger_1.default.debug(`${remoteUrl} (${(0, util_1.toReadableSizeString)(size)}) ` +
248
+ `has been downloaded to '${dstPath}' in ${secondsElapsed.toFixed(3)}s`);
249
+ if (secondsElapsed >= 2) {
250
+ const bytesPerSec = Math.floor(size / secondsElapsed);
251
+ logger_1.default.debug(`Approximate download speed: ${(0, util_1.toReadableSizeString)(bytesPerSec)}/s`);
252
+ }
269
253
  }
270
- }
271
254
  }
272
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJERUZBVUxUX1RJTUVPVVRfTVMiLCJ0b0F4aW9zQXV0aCIsImF1dGgiLCJfIiwiaXNQbGFpbk9iamVjdCIsImF4aW9zQXV0aCIsInVzZXJuYW1lIiwiZ2V0IiwicGFzc3dvcmQiLCJ1cGxvYWRGaWxlVG9IdHRwIiwibG9jYWxGaWxlU3RyZWFtIiwicGFyc2VkVXJpIiwidXBsb2FkT3B0aW9ucyIsIm1ldGhvZCIsInRpbWVvdXQiLCJoZWFkZXJzIiwiZmlsZUZpZWxkTmFtZSIsImZvcm1GaWVsZHMiLCJocmVmIiwicmVxdWVzdE9wdHMiLCJ1cmwiLCJtYXhDb250ZW50TGVuZ3RoIiwiSW5maW5pdHkiLCJtYXhCb2R5TGVuZ3RoIiwiZm9ybSIsIkZvcm1EYXRhIiwiYXBwZW5kIiwicGFpcnMiLCJpc0FycmF5IiwidG9QYWlycyIsImtleSIsInZhbHVlIiwidG9Mb3dlciIsImdldEhlYWRlcnMiLCJkYXRhIiwibG9nIiwiZGVidWciLCJKU09OIiwic3RyaW5naWZ5Iiwib21pdCIsInN0YXR1cyIsInN0YXR1c1RleHQiLCJheGlvcyIsImluZm8iLCJ1cGxvYWRGaWxlVG9GdHAiLCJob3N0bmFtZSIsInBvcnQiLCJwcm90b2NvbCIsInBhdGhuYW1lIiwiZnRwT3B0cyIsImhvc3QiLCJpc1VuZGVmaW5lZCIsInBhcnNlSW50IiwidXNlciIsInBhc3MiLCJCIiwicmVzb2x2ZSIsInJlamVjdCIsIkZ0cCIsInB1dCIsImVyciIsImlzSHR0cFVwbG9hZE9wdGlvbnMiLCJvcHRzIiwiVVJMIiwiaXNOb3RIdHRwVXBsb2FkT3B0aW9ucyIsInVwbG9hZEZpbGUiLCJsb2NhbFBhdGgiLCJyZW1vdGVVcmkiLCJmcyIsImV4aXN0cyIsIkVycm9yIiwiaXNNZXRlcmVkIiwic2l6ZSIsInN0YXQiLCJ0b1JlYWRhYmxlU2l6ZVN0cmluZyIsInRpbWVyIiwiVGltZXIiLCJzdGFydCIsImNyZWF0ZVJlYWRTdHJlYW0iLCJnZXREdXJhdGlvbiIsImFzU2Vjb25kcyIsInRvRml4ZWQiLCJkb3dubG9hZEZpbGUiLCJyZW1vdGVVcmwiLCJkc3RQYXRoIiwiZG93bmxvYWRPcHRpb25zIiwicmVzcG9uc2VUeXBlIiwicmVzcG9uc2VMZW5ndGgiLCJ3cml0ZXIiLCJjcmVhdGVXcml0ZVN0cmVhbSIsInJlc3BvbnNlU3RyZWFtIiwicmVzcG9uc2VIZWFkZXJzIiwicGlwZSIsIm9uY2UiLCJlIiwidW5waXBlIiwibWVzc2FnZSIsInJpbXJhZiIsInNlY29uZHNFbGFwc2VkIiwiYnl0ZXNQZXJTZWMiLCJNYXRoIiwiZmxvb3IiXSwic291cmNlcyI6WyIuLi8uLi9saWIvbmV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgZnMgZnJvbSAnLi9mcyc7XG5pbXBvcnQgQiBmcm9tICdibHVlYmlyZCc7XG5pbXBvcnQge3RvUmVhZGFibGVTaXplU3RyaW5nfSBmcm9tICcuL3V0aWwnO1xuaW1wb3J0IGxvZyBmcm9tICcuL2xvZ2dlcic7XG5pbXBvcnQgRnRwIGZyb20gJ2pzZnRwJztcbmltcG9ydCBUaW1lciBmcm9tICcuL3RpbWluZyc7XG5pbXBvcnQgYXhpb3MgZnJvbSAnYXhpb3MnO1xuaW1wb3J0IEZvcm1EYXRhIGZyb20gJ2Zvcm0tZGF0YSc7XG5cbmNvbnN0IERFRkFVTFRfVElNRU9VVF9NUyA9IDQgKiA2MCAqIDEwMDA7XG5cbi8qKlxuICogQ29udmVydHMge0BsaW5rY29kZSBBdXRoQ3JlZGVudGlhbHN9IHRvIGNyZWRlbnRpYWxzIHVuZGVyc3Rvb2QgYnkge0BsaW5rY29kZSBheGlvc30uXG4gKiBAcGFyYW0ge0F1dGhDcmVkZW50aWFscyB8IGltcG9ydCgnYXhpb3MnKS5BeGlvc0Jhc2ljQ3JlZGVudGlhbHN9IFthdXRoXVxuICogQHJldHVybnMge2ltcG9ydCgnYXhpb3MnKS5BeGlvc0Jhc2ljQ3JlZGVudGlhbHM/fVxuICovXG5mdW5jdGlvbiB0b0F4aW9zQXV0aChhdXRoKSB7XG4gIGlmICghXy5pc1BsYWluT2JqZWN0KGF1dGgpKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBheGlvc0F1dGggPSB7XG4gICAgdXNlcm5hbWU6IF8uZ2V0KGF1dGgsICd1c2VybmFtZScsIF8uZ2V0KGF1dGgsICd1c2VyJykpLFxuICAgIHBhc3N3b3JkOiBfLmdldChhdXRoLCAncGFzc3dvcmQnLCBfLmdldChhdXRoLCAncGFzcycpKSxcbiAgfTtcbiAgcmV0dXJuIGF4aW9zQXV0aC51c2VybmFtZSAmJiBheGlvc0F1dGgucGFzc3dvcmQgPyBheGlvc0F1dGggOiBudWxsO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7Tm9kZUpTLlJlYWRhYmxlU3RyZWFtfSBsb2NhbEZpbGVTdHJlYW1cbiAqIEBwYXJhbSB7VVJMfSBwYXJzZWRVcmlcbiAqIEBwYXJhbSB7SHR0cFVwbG9hZE9wdGlvbnMgJiBOZXRPcHRpb25zfSBbdXBsb2FkT3B0aW9uc11cbiAqL1xuYXN5bmMgZnVuY3Rpb24gdXBsb2FkRmlsZVRvSHR0cChcbiAgbG9jYWxGaWxlU3RyZWFtLFxuICBwYXJzZWRVcmksXG4gIHVwbG9hZE9wdGlvbnMgPSAvKiogQHR5cGUge0h0dHBVcGxvYWRPcHRpb25zICYgTmV0T3B0aW9uc30gKi8gKHt9KVxuKSB7XG4gIGNvbnN0IHtcbiAgICBtZXRob2QgPSAnUE9TVCcsXG4gICAgdGltZW91dCA9IERFRkFVTFRfVElNRU9VVF9NUyxcbiAgICBoZWFkZXJzLFxuICAgIGF1dGgsXG4gICAgZmlsZUZpZWxkTmFtZSA9ICdmaWxlJyxcbiAgICBmb3JtRmllbGRzLFxuICB9ID0gdXBsb2FkT3B0aW9ucztcbiAgY29uc3Qge2hyZWZ9ID0gcGFyc2VkVXJpO1xuXG4gIC8qKiBAdHlwZSB7aW1wb3J0KCdheGlvcycpLkF4aW9zUmVxdWVzdENvbmZpZ30gKi9cbiAgY29uc3QgcmVxdWVzdE9wdHMgPSB7XG4gICAgdXJsOiBocmVmLFxuICAgIG1ldGhvZCxcbiAgICB0aW1lb3V0LFxuICAgIG1heENvbnRlbnRMZW5ndGg6IEluZmluaXR5LFxuICAgIG1heEJvZHlMZW5ndGg6IEluZmluaXR5LFxuICB9O1xuICBjb25zdCBheGlvc0F1dGggPSB0b0F4aW9zQXV0aChhdXRoKTtcbiAgaWYgKGF4aW9zQXV0aCkge1xuICAgIHJlcXVlc3RPcHRzLmF1dGggPSBheGlvc0F1dGg7XG4gIH1cbiAgaWYgKGZpbGVGaWVsZE5hbWUpIHtcbiAgICBjb25zdCBmb3JtID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgZm9ybS5hcHBlbmQoZmlsZUZpZWxkTmFtZSwgbG9jYWxGaWxlU3RyZWFtKTtcbiAgICBpZiAoZm9ybUZpZWxkcykge1xuICAgICAgbGV0IHBhaXJzID0gW107XG4gICAgICBpZiAoXy5pc0FycmF5KGZvcm1GaWVsZHMpKSB7XG4gICAgICAgIHBhaXJzID0gZm9ybUZpZWxkcztcbiAgICAgIH0gZWxzZSBpZiAoXy5pc1BsYWluT2JqZWN0KGZvcm1GaWVsZHMpKSB7XG4gICAgICAgIHBhaXJzID0gXy50b1BhaXJzKGZvcm1GaWVsZHMpO1xuICAgICAgfVxuICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgcGFpcnMpIHtcbiAgICAgICAgaWYgKF8udG9Mb3dlcihrZXkpICE9PSBfLnRvTG93ZXIoZmlsZUZpZWxkTmFtZSkpIHtcbiAgICAgICAgICBmb3JtLmFwcGVuZChrZXksIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXF1ZXN0T3B0cy5oZWFkZXJzID0ge1xuICAgICAgLi4uKF8uaXNQbGFpbk9iamVjdChoZWFkZXJzKSA/IGhlYWRlcnMgOiB7fSksXG4gICAgICAuLi5mb3JtLmdldEhlYWRlcnMoKSxcbiAgICB9O1xuICAgIHJlcXVlc3RPcHRzLmRhdGEgPSBmb3JtO1xuICB9IGVsc2Uge1xuICAgIGlmIChfLmlzUGxhaW5PYmplY3QoaGVhZGVycykpIHtcbiAgICAgIHJlcXVlc3RPcHRzLmhlYWRlcnMgPSBoZWFkZXJzO1xuICAgIH1cbiAgICByZXF1ZXN0T3B0cy5kYXRhID0gbG9jYWxGaWxlU3RyZWFtO1xuICB9XG4gIGxvZy5kZWJ1ZyhcbiAgICBgUGVyZm9ybWluZyAke21ldGhvZH0gdG8gJHtocmVmfSB3aXRoIG9wdGlvbnMgKGV4Y2x1ZGluZyBkYXRhKTogYCArXG4gICAgICBKU09OLnN0cmluZ2lmeShfLm9taXQocmVxdWVzdE9wdHMsIFsnZGF0YSddKSlcbiAgKTtcblxuICBjb25zdCB7c3RhdHVzLCBzdGF0dXNUZXh0fSA9IGF3YWl0IGF4aW9zKHJlcXVlc3RPcHRzKTtcbiAgbG9nLmluZm8oYFNlcnZlciByZXNwb25zZTogJHtzdGF0dXN9ICR7c3RhdHVzVGV4dH1gKTtcbn1cblxuLyoqXG4gKiBAcGFyYW0ge3N0cmluZyB8IEJ1ZmZlciB8IE5vZGVKUy5SZWFkYWJsZVN0cmVhbX0gbG9jYWxGaWxlU3RyZWFtXG4gKiBAcGFyYW0ge1VSTH0gcGFyc2VkVXJpXG4gKiBAcGFyYW0ge05vdEh0dHBVcGxvYWRPcHRpb25zICYgTmV0T3B0aW9uc30gW3VwbG9hZE9wdGlvbnNdXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHVwbG9hZEZpbGVUb0Z0cChcbiAgbG9jYWxGaWxlU3RyZWFtLFxuICBwYXJzZWRVcmksXG4gIHVwbG9hZE9wdGlvbnMgPSAvKiogQHR5cGUge05vdEh0dHBVcGxvYWRPcHRpb25zICYgTmV0T3B0aW9uc30gKi8gKHt9KVxuKSB7XG4gIGNvbnN0IHthdXRofSA9IHVwbG9hZE9wdGlvbnM7XG4gIGNvbnN0IHtob3N0bmFtZSwgcG9ydCwgcHJvdG9jb2wsIHBhdGhuYW1lfSA9IHBhcnNlZFVyaTtcblxuICBjb25zdCBmdHBPcHRzID0ge1xuICAgIGhvc3Q6IGhvc3RuYW1lLFxuICAgIHBvcnQ6ICFfLmlzVW5kZWZpbmVkKHBvcnQpID8gXy5wYXJzZUludChwb3J0KSA6IDIxLFxuICB9O1xuICBpZiAoYXV0aD8udXNlciAmJiBhdXRoPy5wYXNzKSB7XG4gICAgZnRwT3B0cy51c2VyID0gYXV0aC51c2VyO1xuICAgIGZ0cE9wdHMucGFzcyA9IGF1dGgucGFzcztcbiAgfVxuICBsb2cuZGVidWcoYCR7cHJvdG9jb2x9IHVwbG9hZCBvcHRpb25zOiAke0pTT04uc3RyaW5naWZ5KGZ0cE9wdHMpfWApO1xuICByZXR1cm4gYXdhaXQgbmV3IEIoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIG5ldyBGdHAoZnRwT3B0cykucHV0KGxvY2FsRmlsZVN0cmVhbSwgcGF0aG5hbWUsIChlcnIpID0+IHtcbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuXG4vKipcbiAqIFJldHVybnMgYHRydWVgIGlmIHBhcmFtcyBhcmUgdmFsaWQgZm9yIHtAbGlua2NvZGUgdXBsb2FkRmlsZVRvSHR0cH0uXG4gKiBAcGFyYW0ge2FueX0gb3B0c1xuICogQHBhcmFtIHtVUkx9IHVybFxuICogQHJldHVybnMge29wdHMgaXMgSHR0cFVwbG9hZE9wdGlvbnMgJiBOZXRPcHRpb25zfVxuICovXG5mdW5jdGlvbiBpc0h0dHBVcGxvYWRPcHRpb25zKG9wdHMsIHVybCkge1xuICB0cnkge1xuICAgIGNvbnN0IHtwcm90b2NvbH0gPSBuZXcgVVJMKHVybCk7XG4gICAgcmV0dXJuIHByb3RvY29sID09PSAnaHR0cDonIHx8IHByb3RvY29sID09PSAnaHR0cHM6JztcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyBgdHJ1ZWAgaWYgcGFyYW1zIGFyZSB2YWxpZCBmb3Ige0BsaW5rY29kZSB1cGxvYWRGaWxlVG9GdHB9LlxuICogQHBhcmFtIHthbnl9IG9wdHNcbiAqIEBwYXJhbSB7VVJMfSB1cmxcbiAqIEByZXR1cm5zIHtvcHRzIGlzIE5vdEh0dHBVcGxvYWRPcHRpb25zICYgTmV0T3B0aW9uc31cbiAqL1xuZnVuY3Rpb24gaXNOb3RIdHRwVXBsb2FkT3B0aW9ucyhvcHRzLCB1cmwpIHtcbiAgdHJ5IHtcbiAgICBjb25zdCB7cHJvdG9jb2x9ID0gbmV3IFVSTCh1cmwpO1xuICAgIHJldHVybiBwcm90b2NvbCA9PT0gJ2Z0cDonO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cbi8qKlxuICogVXBsb2FkcyB0aGUgZ2l2ZW4gZmlsZSB0byBhIHJlbW90ZSBsb2NhdGlvbi4gSFRUUChTKSBhbmQgRlRQXG4gKiBwcm90b2NvbHMgYXJlIHN1cHBvcnRlZC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbG9jYWxQYXRoIC0gVGhlIHBhdGggdG8gYSBmaWxlIG9uIHRoZSBsb2NhbCBzdG9yYWdlLlxuICogQHBhcmFtIHtzdHJpbmd9IHJlbW90ZVVyaSAtIFRoZSByZW1vdGUgVVJJIHRvIHVwbG9hZCB0aGUgZmlsZSB0by5cbiAqIEBwYXJhbSB7KEh0dHBVcGxvYWRPcHRpb25zfE5vdEh0dHBVcGxvYWRPcHRpb25zKSAmIE5ldE9wdGlvbnN9IFt1cGxvYWRPcHRpb25zXVxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHVwbG9hZEZpbGUoXG4gIGxvY2FsUGF0aCxcbiAgcmVtb3RlVXJpLFxuICB1cGxvYWRPcHRpb25zID0gLyoqIEB0eXBlIHsoSHR0cFVwbG9hZE9wdGlvbnN8Tm90SHR0cFVwbG9hZE9wdGlvbnMpICYgTmV0T3B0aW9uc30gKi8gKHt9KVxuKSB7XG4gIGlmICghKGF3YWl0IGZzLmV4aXN0cyhsb2NhbFBhdGgpKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgJyR7bG9jYWxQYXRofScgZG9lcyBub3QgZXhpc3RzIG9yIGlzIG5vdCBhY2Nlc3NpYmxlYCk7XG4gIH1cblxuICBjb25zdCB7aXNNZXRlcmVkID0gdHJ1ZX0gPSB1cGxvYWRPcHRpb25zO1xuICBjb25zdCB1cmwgPSBuZXcgVVJMKHJlbW90ZVVyaSk7XG4gIGNvbnN0IHtzaXplfSA9IGF3YWl0IGZzLnN0YXQobG9jYWxQYXRoKTtcbiAgaWYgKGlzTWV0ZXJlZCkge1xuICAgIGxvZy5pbmZvKGBVcGxvYWRpbmcgJyR7bG9jYWxQYXRofScgb2YgJHt0b1JlYWRhYmxlU2l6ZVN0cmluZyhzaXplKX0gc2l6ZSB0byAnJHtyZW1vdGVVcml9J2ApO1xuICB9XG4gIGNvbnN0IHRpbWVyID0gbmV3IFRpbWVyKCkuc3RhcnQoKTtcbiAgaWYgKGlzSHR0cFVwbG9hZE9wdGlvbnModXBsb2FkT3B0aW9ucywgdXJsKSkge1xuICAgIGlmICghdXBsb2FkT3B0aW9ucy5maWxlRmllbGROYW1lKSB7XG4gICAgICB1cGxvYWRPcHRpb25zLmhlYWRlcnMgPSB7XG4gICAgICAgIC4uLihfLmlzUGxhaW5PYmplY3QodXBsb2FkT3B0aW9ucy5oZWFkZXJzKSA/IHVwbG9hZE9wdGlvbnMuaGVhZGVycyA6IHt9KSxcbiAgICAgICAgJ0NvbnRlbnQtTGVuZ3RoJzogc2l6ZSxcbiAgICAgIH07XG4gICAgfVxuICAgIGF3YWl0IHVwbG9hZEZpbGVUb0h0dHAoZnMuY3JlYXRlUmVhZFN0cmVhbShsb2NhbFBhdGgpLCB1cmwsIHVwbG9hZE9wdGlvbnMpO1xuICB9IGVsc2UgaWYgKGlzTm90SHR0cFVwbG9hZE9wdGlvbnModXBsb2FkT3B0aW9ucywgdXJsKSkge1xuICAgIGF3YWl0IHVwbG9hZEZpbGVUb0Z0cChmcy5jcmVhdGVSZWFkU3RyZWFtKGxvY2FsUGF0aCksIHVybCwgdXBsb2FkT3B0aW9ucyk7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYENhbm5vdCB1cGxvYWQgdGhlIGZpbGUgYXQgJyR7bG9jYWxQYXRofScgdG8gJyR7cmVtb3RlVXJpfScuIGAgK1xuICAgICAgICBgVW5zdXBwb3J0ZWQgcmVtb3RlIHByb3RvY29sICcke3VybC5wcm90b2NvbH0nLiBgICtcbiAgICAgICAgYE9ubHkgaHR0cC9odHRwcyBhbmQgZnRwL2Z0cHMgcHJvdG9jb2xzIGFyZSBzdXBwb3J0ZWQuYFxuICAgICk7XG4gIH1cbiAgaWYgKGlzTWV0ZXJlZCkge1xuICAgIGxvZy5pbmZvKFxuICAgICAgYFVwbG9hZGVkICcke2xvY2FsUGF0aH0nIG9mICR7dG9SZWFkYWJsZVNpemVTdHJpbmcoc2l6ZSl9IHNpemUgaW4gYCArXG4gICAgICAgIGAke3RpbWVyLmdldER1cmF0aW9uKCkuYXNTZWNvbmRzLnRvRml4ZWQoMyl9c2BcbiAgICApO1xuICB9XG59XG5cbi8qKlxuICogRG93bmxvYWRzIHRoZSBnaXZlbiBmaWxlIHZpYSBIVFRQKFMpXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHJlbW90ZVVybCAtIFRoZSByZW1vdGUgdXJsXG4gKiBAcGFyYW0ge3N0cmluZ30gZHN0UGF0aCAtIFRoZSBsb2NhbCBwYXRoIHRvIGRvd25sb2FkIHRoZSBmaWxlIHRvXG4gKiBAcGFyYW0ge0Rvd25sb2FkT3B0aW9ucyAmIE5ldE9wdGlvbnN9IFtkb3dubG9hZE9wdGlvbnNdXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgZG93bmxvYWQgb3BlcmF0aW9uIGZhaWxzXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGRvd25sb2FkRmlsZShcbiAgcmVtb3RlVXJsLFxuICBkc3RQYXRoLFxuICBkb3dubG9hZE9wdGlvbnMgPSAvKiogQHR5cGUge0Rvd25sb2FkT3B0aW9ucyAmIE5ldE9wdGlvbnN9ICovICh7fSlcbikge1xuICBjb25zdCB7aXNNZXRlcmVkID0gdHJ1ZSwgYXV0aCwgdGltZW91dCA9IERFRkFVTFRfVElNRU9VVF9NUywgaGVhZGVyc30gPSBkb3dubG9hZE9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIEB0eXBlIHtpbXBvcnQoJ2F4aW9zJykuQXhpb3NSZXF1ZXN0Q29uZmlnfVxuICAgKi9cbiAgY29uc3QgcmVxdWVzdE9wdHMgPSB7XG4gICAgdXJsOiByZW1vdGVVcmwsXG4gICAgcmVzcG9uc2VUeXBlOiAnc3RyZWFtJyxcbiAgICB0aW1lb3V0LFxuICB9O1xuICBjb25zdCBheGlvc0F1dGggPSB0b0F4aW9zQXV0aChhdXRoKTtcbiAgaWYgKGF4aW9zQXV0aCkge1xuICAgIHJlcXVlc3RPcHRzLmF1dGggPSBheGlvc0F1dGg7XG4gIH1cbiAgaWYgKF8uaXNQbGFpbk9iamVjdChoZWFkZXJzKSkge1xuICAgIHJlcXVlc3RPcHRzLmhlYWRlcnMgPSBoZWFkZXJzO1xuICB9XG5cbiAgY29uc3QgdGltZXIgPSBuZXcgVGltZXIoKS5zdGFydCgpO1xuICBsZXQgcmVzcG9uc2VMZW5ndGg7XG4gIHRyeSB7XG4gICAgY29uc3Qgd3JpdGVyID0gZnMuY3JlYXRlV3JpdGVTdHJlYW0oZHN0UGF0aCk7XG4gICAgY29uc3Qge2RhdGE6IHJlc3BvbnNlU3RyZWFtLCBoZWFkZXJzOiByZXNwb25zZUhlYWRlcnN9ID0gYXdhaXQgYXhpb3MocmVxdWVzdE9wdHMpO1xuICAgIHJlc3BvbnNlTGVuZ3RoID0gcGFyc2VJbnQocmVzcG9uc2VIZWFkZXJzWydjb250ZW50LWxlbmd0aCddLCAxMCk7XG4gICAgcmVzcG9uc2VTdHJlYW0ucGlwZSh3cml0ZXIpO1xuXG4gICAgYXdhaXQgbmV3IEIoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgcmVzcG9uc2VTdHJlYW0ub25jZSgnZXJyb3InLCByZWplY3QpO1xuICAgICAgd3JpdGVyLm9uY2UoJ2ZpbmlzaCcsIHJlc29sdmUpO1xuICAgICAgd3JpdGVyLm9uY2UoJ2Vycm9yJywgKGUpID0+IHtcbiAgICAgICAgcmVzcG9uc2VTdHJlYW0udW5waXBlKHdyaXRlcik7XG4gICAgICAgIHJlamVjdChlKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBkb3dubG9hZCB0aGUgZmlsZSBmcm9tICR7cmVtb3RlVXJsfTogJHtlcnIubWVzc2FnZX1gKTtcbiAgfVxuXG4gIGNvbnN0IHtzaXplfSA9IGF3YWl0IGZzLnN0YXQoZHN0UGF0aCk7XG4gIGlmIChyZXNwb25zZUxlbmd0aCAmJiBzaXplICE9PSByZXNwb25zZUxlbmd0aCkge1xuICAgIGF3YWl0IGZzLnJpbXJhZihkc3RQYXRoKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgVGhlIHNpemUgb2YgdGhlIGZpbGUgZG93bmxvYWRlZCBmcm9tICR7cmVtb3RlVXJsfSAoJHtzaXplfSBieXRlcykgYCArXG4gICAgICAgIGBkaWZmZXJzIGZyb20gdGhlIG9uZSBpbiBDb250ZW50LUxlbmd0aCByZXNwb25zZSBoZWFkZXIgKCR7cmVzcG9uc2VMZW5ndGh9IGJ5dGVzKWBcbiAgICApO1xuICB9XG4gIGlmIChpc01ldGVyZWQpIHtcbiAgICBjb25zdCBzZWNvbmRzRWxhcHNlZCA9IHRpbWVyLmdldER1cmF0aW9uKCkuYXNTZWNvbmRzO1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGAke3JlbW90ZVVybH0gKCR7dG9SZWFkYWJsZVNpemVTdHJpbmcoc2l6ZSl9KSBgICtcbiAgICAgICAgYGhhcyBiZWVuIGRvd25sb2FkZWQgdG8gJyR7ZHN0UGF0aH0nIGluICR7c2Vjb25kc0VsYXBzZWQudG9GaXhlZCgzKX1zYFxuICAgICk7XG4gICAgaWYgKHNlY29uZHNFbGFwc2VkID49IDIpIHtcbiAgICAgIGNvbnN0IGJ5dGVzUGVyU2VjID0gTWF0aC5mbG9vcihzaXplIC8gc2Vjb25kc0VsYXBzZWQpO1xuICAgICAgbG9nLmRlYnVnKGBBcHByb3hpbWF0ZSBkb3dubG9hZCBzcGVlZDogJHt0b1JlYWRhYmxlU2l6ZVN0cmluZyhieXRlc1BlclNlYyl9L3NgKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IHt1cGxvYWRGaWxlLCBkb3dubG9hZEZpbGV9O1xuXG4vKipcbiAqIENvbW1vbiBvcHRpb25zIGZvciB7QGxpbmtjb2RlIHVwbG9hZEZpbGV9IGFuZCB7QGxpbmtjb2RlIGRvd25sb2FkRmlsZX0uXG4gKiBAdHlwZWRlZiBOZXRPcHRpb25zXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtpc01ldGVyZWQ9dHJ1ZV0gLSBXaGV0aGVyIHRvIGxvZyB0aGUgYWN0dWFsIGRvd25sb2FkIHBlcmZvcm1hbmNlXG4gKiAoZS5nLiB0aW1pbmdzIGFuZCBzcGVlZClcbiAqIEBwcm9wZXJ0eSB7QXV0aENyZWRlbnRpYWxzfSBbYXV0aF0gLSBBdXRoZW50aWNhdGlvbiBjcmVkZW50aWFsc1xuICovXG5cbi8qKlxuICogU3BlY2lmaWMgb3B0aW9ucyBmb3Ige0BsaW5rY29kZSBkb3dubG9hZEZpbGV9LlxuICogQHR5cGVkZWYgRG93bmxvYWRPcHRpb25zXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3RpbWVvdXRdIC0gVGhlIGFjdHVhbCByZXF1ZXN0IHRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzOyBkZWZhdWx0cyB0byB7QGxpbmtjb2RlIERFRkFVTFRfVElNRU9VVF9NU31cbiAqIEBwcm9wZXJ0eSB7UmVjb3JkPHN0cmluZyxhbnk+fSBbaGVhZGVyc10gLSBSZXF1ZXN0IGhlYWRlcnMgbWFwcGluZ1xuICovXG5cbi8qKlxuICogQmFzaWMgYXV0aCBjcmVkZW50aWFsczsgdXNlZCBieSB7QGxpbmtjb2RlIE5ldE9wdGlvbnN9LlxuICogQHR5cGVkZWYgQXV0aENyZWRlbnRpYWxzXG4gKiBAcHJvcGVydHkge3N0cmluZ30gdXNlciAtIE5vbi1lbXB0eSB1c2VyIG5hbWVcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBwYXNzIC0gTm9uLWVtcHR5IHBhc3N3b3JkXG4gKi9cblxuLyoqXG4gKiBUaGlzIHR5cGUgaXMgdXNlZCBpbiB7QGxpbmtjb2RlIHVwbG9hZEZpbGV9IGlmIHRoZSByZW1vdGUgbG9jYXRpb24gdXNlcyB0aGUgYGZ0cGAgcHJvdG9jb2wsIGFuZCBkaXN0aW5ndWlzaGVzIHRoZSB0eXBlIGZyb20ge0BsaW5rY29kZSBIdHRwVXBsb2FkT3B0aW9uc30uXG4gKiBAdHlwZWRlZiBOb3RIdHRwVXBsb2FkT3B0aW9uc1xuICogQHByb3BlcnR5IHtuZXZlcn0gaGVhZGVyc1xuICogQHByb3BlcnR5IHtuZXZlcn0gbWV0aG9kXG4gKiBAcHJvcGVydHkge25ldmVyfSB0aW1lb3V0XG4gKiBAcHJvcGVydHkge25ldmVyfSBmaWxlRmllbGROYW1lXG4gKiBAcHJvcGVydHkge25ldmVyfSBmb3JtRmllbGRzXG4gKi9cblxuLyoqXG4gKiBTcGVjaWZpYyBvcHRpb25zIGZvciB7QGxpbmtjb2RlIHVwbG9hZEZpbGV9IGlmIHRoZSByZW1vdGUgbG9jYXRpb24gdXNlcyB0aGUgYGh0dHAocylgIHByb3RvY29sXG4gKiBAdHlwZWRlZiBIdHRwVXBsb2FkT3B0aW9uc1xuICogQHByb3BlcnR5IHtSZWNvcmQ8c3RyaW5nLGFueT59IGhlYWRlcnMgLSBBZGRpdGlvbmFsIHJlcXVlc3QgaGVhZGVycyBtYXBwaW5nXG4gKiBAcHJvcGVydHkge2ltcG9ydCgnYXhpb3MnKS5NZXRob2R9IFttZXRob2Q9J1BPU1QnXSAtIFRoZSBIVFRQIG1ldGhvZCB1c2VkIGZvciBmaWxlIHVwbG9hZFxuICogQHByb3BlcnR5IHtudW1iZXJ9IFt0aW1lb3V0XSAtIFRoZSBhY3R1YWwgcmVxdWVzdCB0aW1lb3V0IGluIG1pbGxpc2Vjb25kczsgZGVmYXVsdHMgdG8ge0BsaW5rY29kZSBERUZBVUxUX1RJTUVPVVRfTVN9XG4gKiBAcHJvcGVydHkge3N0cmluZ30gW2ZpbGVGaWVsZE5hbWU9J2ZpbGUnXSAtIFRoZSBuYW1lIG9mIHRoZSBmb3JtIGZpZWxkIGNvbnRhaW5pbmcgdGhlIGZpbGVcbiAqIGNvbnRlbnQgdG8gYmUgdXBsb2FkZWQuIEFueSBmYWxzeSB2YWx1ZSBtYWtlIHRoZSByZXF1ZXN0IHRvIHVzZSBub24tbXVsdGlwYXJ0IHVwbG9hZFxuICogQHByb3BlcnR5IHtSZWNvcmQ8c3RyaW5nLGFueT59IFtmb3JtRmllbGRzXSAtIFRoZSBhZGRpdGlvbmFsIGZvcm0gZmllbGRzXG4gKiB0byBiZSBpbmNsdWRlZCBpbnRvIHRoZSB1cGxvYWQgcmVxdWVzdC4gVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IGNvbnNpZGVyZWQgaWZcbiAqIGBmaWxlRmllbGROYW1lYCBpcyBzZXRcbiAqL1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFFQSxNQUFNQSxrQkFBa0IsR0FBRyxJQUFJLEVB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
255
+ exports.downloadFile = downloadFile;
256
+ /**
257
+ * Common options for {@linkcode uploadFile} and {@linkcode downloadFile}.
258
+ * @typedef NetOptions
259
+ * @property {boolean} [isMetered=true] - Whether to log the actual download performance
260
+ * (e.g. timings and speed)
261
+ * @property {AuthCredentials} [auth] - Authentication credentials
262
+ */
263
+ /**
264
+ * Specific options for {@linkcode downloadFile}.
265
+ * @typedef DownloadOptions
266
+ * @property {number} [timeout] - The actual request timeout in milliseconds; defaults to {@linkcode DEFAULT_TIMEOUT_MS}
267
+ * @property {Record<string,any>} [headers] - Request headers mapping
268
+ */
269
+ /**
270
+ * Basic auth credentials; used by {@linkcode NetOptions}.
271
+ * @typedef AuthCredentials
272
+ * @property {string} user - Non-empty user name
273
+ * @property {string} pass - Non-empty password
274
+ */
275
+ /**
276
+ * This type is used in {@linkcode uploadFile} if the remote location uses the `ftp` protocol, and distinguishes the type from {@linkcode HttpUploadOptions}.
277
+ * @typedef NotHttpUploadOptions
278
+ * @property {never} headers
279
+ * @property {never} method
280
+ * @property {never} timeout
281
+ * @property {never} fileFieldName
282
+ * @property {never} formFields
283
+ */
284
+ /**
285
+ * Specific options for {@linkcode uploadFile} if the remote location uses the `http(s)` protocol
286
+ * @typedef HttpUploadOptions
287
+ * @property {Record<string,any>} headers - Additional request headers mapping
288
+ * @property {import('axios').Method} [method='POST'] - The HTTP method used for file upload
289
+ * @property {number} [timeout] - The actual request timeout in milliseconds; defaults to {@linkcode DEFAULT_TIMEOUT_MS}
290
+ * @property {string} [fileFieldName='file'] - The name of the form field containing the file
291
+ * content to be uploaded. Any falsy value make the request to use non-multipart upload
292
+ * @property {Record<string,any>} [formFields] - The additional form fields
293
+ * to be included into the upload request. This property is only considered if
294
+ * `fileFieldName` is set
295
+ */
296
+ //# sourceMappingURL=net.js.map