@appium/support 2.54.2 → 2.55.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/lib/fs.js +1 -1
- package/build/lib/image-util.js +17 -10
- package/build/lib/index.js +98 -0
- package/build/lib/log-internal.js +1 -1
- package/build/lib/logging.js +4 -3
- package/build/lib/net.js +6 -4
- package/build/lib/plist.js +4 -4
- package/build/lib/system.js +3 -3
- package/build/lib/tempdir.js +1 -1
- package/build/lib/timing.js +1 -1
- package/build/lib/util.js +17 -17
- package/build/lib/zip.js +25 -15
- package/build/test/assets/sample_binary.plist +0 -0
- package/build/test/assets/sample_text.plist +28 -0
- package/build/test/fs-specs.js +264 -0
- package/build/test/helpers.js +35 -0
- package/build/test/image-util-e2e-specs.js +227 -0
- package/build/test/index-specs.js +49 -0
- package/build/test/log-internals-specs.js +97 -0
- package/build/test/logger/helpers.js +71 -0
- package/build/test/logger/logger-force-specs.js +41 -0
- package/build/test/logger/logger-normal-specs.js +113 -0
- package/build/test/logger/logger-test-specs.js +40 -0
- package/build/test/mjpeg-e2e-specs.js +96 -0
- package/build/test/net-e2e-specs.js +32 -0
- package/build/test/node-e2e-specs.js +22 -0
- package/build/test/plist-specs.js +54 -0
- package/build/test/process-specs.js +104 -0
- package/build/test/system-specs.js +136 -0
- package/build/test/tempdir-specs.js +86 -0
- package/build/test/timing-specs.js +125 -0
- package/build/test/util-e2e-specs.js +136 -0
- package/build/test/util-specs.js +537 -0
- package/build/test/zip-e2e-specs.js +233 -0
- package/index.js +1 -28
- package/lib/image-util.js +15 -7
- package/lib/index.js +28 -0
- package/lib/log-internal.js +1 -1
- package/lib/logging.js +1 -1
- package/lib/net.js +5 -4
- package/lib/zip.js +45 -31
- package/package.json +9 -15
- package/build/index.js +0 -98
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
require("source-map-support/register");
|
|
6
|
+
|
|
7
|
+
var _path = _interopRequireDefault(require("path"));
|
|
8
|
+
|
|
9
|
+
var zip = _interopRequireWildcard(require("../lib/zip"));
|
|
10
|
+
|
|
11
|
+
var _index = require("../lib/index");
|
|
12
|
+
|
|
13
|
+
var _helpers = require("./helpers");
|
|
14
|
+
|
|
15
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
16
|
+
|
|
17
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
18
|
+
|
|
19
|
+
describe('#zip', function () {
|
|
20
|
+
const optionMap = new Map([['native JS unzip', {}], ['system unzip', {
|
|
21
|
+
useSystemUnzip: true
|
|
22
|
+
}]]);
|
|
23
|
+
optionMap.forEach((options, desc) => {
|
|
24
|
+
describe(desc, function () {
|
|
25
|
+
let assetsPath;
|
|
26
|
+
let zippedFilePath;
|
|
27
|
+
let tmpRoot;
|
|
28
|
+
beforeEach(async function () {
|
|
29
|
+
assetsPath = await _index.tempDir.openDir();
|
|
30
|
+
tmpRoot = await _index.tempDir.openDir();
|
|
31
|
+
const zippedBase64 = 'UEsDBAoAAAAAALlzk0oAAAAAAAAAAAAAAAAJABAAdW56aXBwZWQvVVgMANBO+VjO1vdY9QEUAFBLAwQKAAAAAADAc5NKAAAAAAAAAAAAAAAAEgAQAHVuemlwcGVkL3Rlc3QtZGlyL1VYDADQTvlY19b3WPUBFABQSwMEFAAIAAgAwnOTSgAAAAAAAAAAAAAAABcAEAB1bnppcHBlZC90ZXN0LWRpci9hLnR4dFVYDACDTvlY3Nb3WPUBFADzSM3JyVcIzy/KSQEAUEsHCFaxF0oNAAAACwAAAFBLAwQUAAgACADEc5NKAAAAAAAAAAAAAAAAFwAQAHVuemlwcGVkL3Rlc3QtZGlyL2IudHh0VVgMAINO+Vjf1vdY9QEUAHPLz1dwSiwCAFBLBwhIfrZJCQAAAAcAAABQSwECFQMKAAAAAAC5c5NKAAAAAAAAAAAAAAAACQAMAAAAAAAAAABA7UEAAAAAdW56aXBwZWQvVVgIANBO+VjO1vdYUEsBAhUDCgAAAAAAwHOTSgAAAAAAAAAAAAAAABIADAAAAAAAAAAAQO1BNwAAAHVuemlwcGVkL3Rlc3QtZGlyL1VYCADQTvlY19b3WFBLAQIVAxQACAAIAMJzk0pWsRdKDQAAAAsAAAAXAAwAAAAAAAAAAECkgXcAAAB1bnppcHBlZC90ZXN0LWRpci9hLnR4dFVYCACDTvlY3Nb3WFBLAQIVAxQACAAIAMRzk0pIfrZJCQAAAAcAAAAXAAwAAAAAAAAAAECkgdkAAAB1bnppcHBlZC90ZXN0LWRpci9iLnR4dFVYCACDTvlY39b3WFBLBQYAAAAABAAEADEBAAA3AQAAAAA=';
|
|
32
|
+
zippedFilePath = _path.default.resolve(tmpRoot, 'zipped.zip');
|
|
33
|
+
await _index.fs.writeFile(zippedFilePath, zippedBase64, 'base64');
|
|
34
|
+
await zip.extractAllTo(zippedFilePath, assetsPath, options);
|
|
35
|
+
});
|
|
36
|
+
afterEach(async function () {
|
|
37
|
+
for (const tmpPath of [assetsPath, tmpRoot]) {
|
|
38
|
+
if (!(await _index.fs.exists(tmpPath))) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
await _index.fs.rimraf(tmpPath);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
describe('extractAllTo()', function () {
|
|
46
|
+
it('should extract contents of a .zip file to a directory', async function () {
|
|
47
|
+
await _index.fs.readFile(_path.default.resolve(assetsPath, 'unzipped', 'test-dir', 'a.txt'), {
|
|
48
|
+
encoding: 'utf8'
|
|
49
|
+
}).should.eventually.equal('Hello World');
|
|
50
|
+
await _index.fs.readFile(_path.default.resolve(assetsPath, 'unzipped', 'test-dir', 'b.txt'), {
|
|
51
|
+
encoding: 'utf8'
|
|
52
|
+
}).should.eventually.equal('Foo Bar');
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
describe('assertValidZip', function () {
|
|
56
|
+
it('should not throw an error if a valid ZIP file is passed', async function () {
|
|
57
|
+
await zip.assertValidZip(zippedFilePath).should.eventually.be.fulfilled;
|
|
58
|
+
});
|
|
59
|
+
it('should throw an error if the file does not exist', async function () {
|
|
60
|
+
await zip.assertValidZip('blabla').should.eventually.be.rejected;
|
|
61
|
+
});
|
|
62
|
+
it('should throw an error if the file is invalid', async function () {
|
|
63
|
+
await zip.assertValidZip(_path.default.resolve(assetsPath, 'unzipped', 'test-dir', 'a.txt')).should.eventually.be.rejected;
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('readEntries()', function () {
|
|
67
|
+
const expectedEntries = [{
|
|
68
|
+
name: 'unzipped/'
|
|
69
|
+
}, {
|
|
70
|
+
name: 'unzipped/test-dir/'
|
|
71
|
+
}, {
|
|
72
|
+
name: 'unzipped/test-dir/a.txt',
|
|
73
|
+
contents: 'Hello World'
|
|
74
|
+
}, {
|
|
75
|
+
name: 'unzipped/test-dir/b.txt',
|
|
76
|
+
contents: 'Foo Bar'
|
|
77
|
+
}];
|
|
78
|
+
it('should iterate entries (directories and files) of zip file', async function () {
|
|
79
|
+
let i = 0;
|
|
80
|
+
await zip.readEntries(zippedFilePath, async ({
|
|
81
|
+
entry,
|
|
82
|
+
extractEntryTo
|
|
83
|
+
}) => {
|
|
84
|
+
entry.fileName.should.equal(expectedEntries[i].name);
|
|
85
|
+
|
|
86
|
+
if (expectedEntries[i].contents) {
|
|
87
|
+
await extractEntryTo(tmpRoot);
|
|
88
|
+
await _index.fs.readFile(_path.default.resolve(tmpRoot, entry.fileName), {
|
|
89
|
+
flags: 'r',
|
|
90
|
+
encoding: 'utf8'
|
|
91
|
+
}).should.eventually.equal(expectedEntries[i].contents);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
i++;
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
it('should stop iterating zipFile if onEntry callback returns false', async function () {
|
|
98
|
+
let i = 0;
|
|
99
|
+
await zip.readEntries(zippedFilePath, async () => {
|
|
100
|
+
i++;
|
|
101
|
+
return false;
|
|
102
|
+
});
|
|
103
|
+
i.should.equal(1);
|
|
104
|
+
});
|
|
105
|
+
it('should be rejected if it uses a non-zip file', async function () {
|
|
106
|
+
let promise = zip.readEntries(_path.default.resolve(assetsPath, 'unzipped', 'test-dir', 'a.txt'), async () => {});
|
|
107
|
+
await promise.should.eventually.be.rejected;
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
describe('toInMemoryZip()', function () {
|
|
111
|
+
it('should convert a local file to an in-memory zip buffer', async function () {
|
|
112
|
+
const testFolder = _path.default.resolve(assetsPath, 'unzipped');
|
|
113
|
+
|
|
114
|
+
const buffer = await zip.toInMemoryZip(testFolder);
|
|
115
|
+
Buffer.isBuffer(buffer).should.be.true;
|
|
116
|
+
await _index.fs.writeFile(_path.default.resolve(tmpRoot, 'test.zip'), buffer);
|
|
117
|
+
await zip.extractAllTo(_path.default.resolve(tmpRoot, 'test.zip'), _path.default.resolve(tmpRoot, 'output'), {
|
|
118
|
+
fileNamesEncoding: 'utf8'
|
|
119
|
+
});
|
|
120
|
+
await _index.fs.readFile(_path.default.resolve(tmpRoot, 'output', 'test-dir', 'a.txt'), {
|
|
121
|
+
encoding: 'utf8'
|
|
122
|
+
}).should.eventually.equal('Hello World');
|
|
123
|
+
await _index.fs.readFile(_path.default.resolve(tmpRoot, 'output', 'test-dir', 'b.txt'), {
|
|
124
|
+
encoding: 'utf8'
|
|
125
|
+
}).should.eventually.equal('Foo Bar');
|
|
126
|
+
});
|
|
127
|
+
it('should convert a local folder to an in-memory base64-encoded zip buffer', async function () {
|
|
128
|
+
const testFolder = _path.default.resolve(assetsPath, 'unzipped');
|
|
129
|
+
|
|
130
|
+
const buffer = await zip.toInMemoryZip(testFolder, {
|
|
131
|
+
encodeToBase64: true
|
|
132
|
+
});
|
|
133
|
+
await _index.fs.writeFile(_path.default.resolve(tmpRoot, 'test.zip'), Buffer.from(buffer.toString(), 'base64'));
|
|
134
|
+
await zip.extractAllTo(_path.default.resolve(tmpRoot, 'test.zip'), _path.default.resolve(tmpRoot, 'output'));
|
|
135
|
+
await _index.fs.readFile(_path.default.resolve(tmpRoot, 'output', 'test-dir', 'a.txt'), {
|
|
136
|
+
encoding: 'utf8'
|
|
137
|
+
}).should.eventually.equal('Hello World');
|
|
138
|
+
await _index.fs.readFile(_path.default.resolve(tmpRoot, 'output', 'test-dir', 'b.txt'), {
|
|
139
|
+
encoding: 'utf8'
|
|
140
|
+
}).should.eventually.equal('Foo Bar');
|
|
141
|
+
});
|
|
142
|
+
it('should be rejected if use a bad path', async function () {
|
|
143
|
+
await zip.toInMemoryZip(_path.default.resolve(assetsPath, 'bad_path')).should.be.rejectedWith(/no such/i);
|
|
144
|
+
});
|
|
145
|
+
it('should be rejected if max size is exceeded', async function () {
|
|
146
|
+
const testFolder = _path.default.resolve(assetsPath, 'unzipped');
|
|
147
|
+
|
|
148
|
+
await zip.toInMemoryZip(testFolder, {
|
|
149
|
+
maxSize: 1
|
|
150
|
+
}).should.be.rejectedWith(/must not be greater/);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
describe('_extractEntryTo()', function () {
|
|
154
|
+
let entry, mockZipFile, mockZipStream;
|
|
155
|
+
beforeEach(async function () {
|
|
156
|
+
entry = {
|
|
157
|
+
fileName: _path.default.resolve(await _index.tempDir.openDir(), 'temp', 'file')
|
|
158
|
+
};
|
|
159
|
+
mockZipStream = new _helpers.MockReadWriteStream();
|
|
160
|
+
mockZipFile = {
|
|
161
|
+
openReadStream: (entry, cb) => cb(null, mockZipStream)
|
|
162
|
+
};
|
|
163
|
+
});
|
|
164
|
+
it('should be rejected if zip stream emits an error', async function () {
|
|
165
|
+
mockZipStream.pipe = () => {
|
|
166
|
+
mockZipStream.emit('error', new Error('zip stream error'));
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
await zip._extractEntryTo(mockZipFile, entry).should.be.rejectedWith('zip stream error');
|
|
170
|
+
});
|
|
171
|
+
it('should be rejected if write stream emits an error', async function () {
|
|
172
|
+
mockZipStream.pipe = writeStream => {
|
|
173
|
+
writeStream.emit('error', new Error('write stream error'));
|
|
174
|
+
mockZipStream.end();
|
|
175
|
+
writeStream.end();
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
await zip._extractEntryTo(mockZipFile, entry).should.be.rejectedWith('write stream error');
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
describe('toArchive', function () {
|
|
182
|
+
it('should zip all files into an archive', async function () {
|
|
183
|
+
const testFolder = _path.default.resolve(assetsPath, 'unzipped');
|
|
184
|
+
|
|
185
|
+
const dstPath = _path.default.resolve(tmpRoot, 'test.zip');
|
|
186
|
+
|
|
187
|
+
await zip.toArchive(dstPath, {
|
|
188
|
+
cwd: testFolder
|
|
189
|
+
});
|
|
190
|
+
await zip.extractAllTo(dstPath, _path.default.resolve(tmpRoot, 'output'));
|
|
191
|
+
await _index.fs.readFile(_path.default.resolve(tmpRoot, 'output', 'test-dir', 'a.txt'), {
|
|
192
|
+
encoding: 'utf8'
|
|
193
|
+
}).should.eventually.equal('Hello World');
|
|
194
|
+
await _index.fs.readFile(_path.default.resolve(tmpRoot, 'output', 'test-dir', 'b.txt'), {
|
|
195
|
+
encoding: 'utf8'
|
|
196
|
+
}).should.eventually.equal('Foo Bar');
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
describe('unicode filename handling', function () {
|
|
202
|
+
let zippedFilePath, assetsPath, tmpRoot;
|
|
203
|
+
beforeEach(async function () {
|
|
204
|
+
assetsPath = await _index.tempDir.openDir();
|
|
205
|
+
tmpRoot = await _index.tempDir.openDir();
|
|
206
|
+
const zippedBase64 = 'UEsDBBQACAAIABF8/EYAAAAAAAAAABoAAAATACAAa2Fuamkt5q2j5LiW5LiVLmFwcFVUDQAHAgO4VVpX+GBZV/hgdXgLAAEE9QEAAAQUAAAAK8nILFYAorz8EoWi1MScnEqFxDyFxIICLgBQSwcIR93jPhoAAAAaAAAAUEsBAhQDFAAIAAgAEXz8Rkfd4z4aAAAAGgAAABMAIAAAAAAAAAAAAKSBAAAAAGthbmppLeato+S4luS4lS5hcHBVVA0ABwIDuFVaV/hgWVf4YHV4CwABBPUBAAAEFAAAAFBLBQYAAAAAAQABAGEAAAB7AAAAAAA=';
|
|
207
|
+
zippedFilePath = _path.default.resolve(tmpRoot, 'zipped.zip');
|
|
208
|
+
await _index.fs.writeFile(zippedFilePath, zippedBase64, 'base64');
|
|
209
|
+
await zip.extractAllTo(zippedFilePath, assetsPath, {
|
|
210
|
+
useSystemUnzip: true
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
afterEach(async function () {
|
|
214
|
+
for (const tmpPath of [assetsPath, tmpRoot]) {
|
|
215
|
+
if (!(await _index.fs.exists(tmpPath))) {
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
await _index.fs.rimraf(tmpPath);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
it('should retain the proper filenames', async function () {
|
|
223
|
+
const expectedPath = _path.default.join(assetsPath, 'kanji-正世丕.app');
|
|
224
|
+
|
|
225
|
+
if (!(await _index.fs.exists(expectedPath))) {
|
|
226
|
+
throw new chai.AssertionError(`Expected ${expectedPath} to exist, but it does not`);
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
});require('source-map-support').install();
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvemlwLWUyZS1zcGVjcy5qcyJdLCJuYW1lcyI6WyJkZXNjcmliZSIsIm9wdGlvbk1hcCIsIk1hcCIsInVzZVN5c3RlbVVuemlwIiwiZm9yRWFjaCIsIm9wdGlvbnMiLCJkZXNjIiwiYXNzZXRzUGF0aCIsInppcHBlZEZpbGVQYXRoIiwidG1wUm9vdCIsImJlZm9yZUVhY2giLCJ0ZW1wRGlyIiwib3BlbkRpciIsInppcHBlZEJhc2U2NCIsInBhdGgiLCJyZXNvbHZlIiwiZnMiLCJ3cml0ZUZpbGUiLCJ6aXAiLCJleHRyYWN0QWxsVG8iLCJhZnRlckVhY2giLCJ0bXBQYXRoIiwiZXhpc3RzIiwicmltcmFmIiwiaXQiLCJyZWFkRmlsZSIsImVuY29kaW5nIiwic2hvdWxkIiwiZXZlbnR1YWxseSIsImVxdWFsIiwiYXNzZXJ0VmFsaWRaaXAiLCJiZSIsImZ1bGZpbGxlZCIsInJlamVjdGVkIiwiZXhwZWN0ZWRFbnRyaWVzIiwibmFtZSIsImNvbnRlbnRzIiwiaSIsInJlYWRFbnRyaWVzIiwiZW50cnkiLCJleHRyYWN0RW50cnlUbyIsImZpbGVOYW1lIiwiZmxhZ3MiLCJwcm9taXNlIiwidGVzdEZvbGRlciIsImJ1ZmZlciIsInRvSW5NZW1vcnlaaXAiLCJCdWZmZXIiLCJpc0J1ZmZlciIsInRydWUiLCJmaWxlTmFtZXNFbmNvZGluZyIsImVuY29kZVRvQmFzZTY0IiwiZnJvbSIsInRvU3RyaW5nIiwicmVqZWN0ZWRXaXRoIiwibWF4U2l6ZSIsIm1vY2taaXBGaWxlIiwibW9ja1ppcFN0cmVhbSIsIk1vY2tSZWFkV3JpdGVTdHJlYW0iLCJvcGVuUmVhZFN0cmVhbSIsImNiIiwicGlwZSIsImVtaXQiLCJFcnJvciIsIl9leHRyYWN0RW50cnlUbyIsIndyaXRlU3RyZWFtIiwiZW5kIiwiZHN0UGF0aCIsInRvQXJjaGl2ZSIsImN3ZCIsImV4cGVjdGVkUGF0aCIsImpvaW4iLCJjaGFpIiwiQXNzZXJ0aW9uRXJyb3IiXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFB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QUFTLENBQUMsa0JBQWtCO0FBQzFCLFdBQUssTUFBTUMsT0FBWCxJQUFzQixDQUFDZCxVQUFELEVBQWFFLE9BQWIsQ0FBdEIsRUFBNkM7QUFDM0MsWUFBSSxFQUFDLE1BQU1PLFVBQUdNLE1BQUgsQ0FBVUQsT0FBVixDQUFQLENBQUosRUFBK0I7QUFDN0I7QUFDRDs7QUFDRCxjQUFNTCxVQUFHTyxNQUFILENBQVVGLE9BQVYsQ0FBTjtBQUNEO0FBQ0YsS0FQUSxDQUFUO0FBU0FHLElBQUFBLEVBQUUsQ0FBQyxvQ0FBRCxFQUF1QyxrQkFBa0I7QUFDekQsWUFBTThDLFlBQVksR0FBR3hELGNBQUt5RCxJQUFMLENBQVVoRSxVQUFWLEVBQXNCLGVBQXRCLENBQXJCOztBQUVBLFVBQUksRUFBQyxNQUFNUyxVQUFHTSxNQUFILENBQVVnRCxZQUFWLENBQVAsQ0FBSixFQUFvQztBQUNsQyxjQUFNLElBQUlFLElBQUksQ0FBQ0MsY0FBVCxDQUF5QixZQUFXSCxZQUFhLDRCQUFqRCxDQUFOO0FBQ0Q7QUFDRixLQU5DLENBQUY7QUFPRCxHQTdCTyxDQUFSO0FBOEJELENBNU5PLENBQVIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCAqIGFzIHppcCBmcm9tICcuLi9saWIvemlwJztcbmltcG9ydCB7IHRlbXBEaXIsIGZzIH0gZnJvbSAnLi4vbGliL2luZGV4JztcbmltcG9ydCB7IE1vY2tSZWFkV3JpdGVTdHJlYW0gfSBmcm9tICcuL2hlbHBlcnMnO1xuXG5cbmRlc2NyaWJlKCcjemlwJywgZnVuY3Rpb24gKCkge1xuXG4gIGNvbnN0IG9wdGlvbk1hcCA9IG5ldyBNYXAoW1snbmF0aXZlIEpTIHVuemlwJywge31dLCBbJ3N5c3RlbSB1bnppcCcsIHt1c2VTeXN0ZW1VbnppcDogdHJ1ZX1dXSk7XG5cbiAgb3B0aW9uTWFwLmZvckVhY2goKG9wdGlvbnMsIGRlc2MpID0+IHtcbiAgICBkZXNjcmliZShkZXNjLCBmdW5jdGlvbiAoKSB7XG4gICAgICBsZXQgYXNzZXRzUGF0aDtcbiAgICAgIGxldCB6aXBwZWRGaWxlUGF0aDtcbiAgICAgIGxldCB0bXBSb290O1xuXG4gICAgICBiZWZvcmVFYWNoKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYXNzZXRzUGF0aCA9IGF3YWl0IHRlbXBEaXIub3BlbkRpcigpO1xuICAgICAgICB0bXBSb290ID0gYXdhaXQgdGVtcERpci5vcGVuRGlyKCk7XG4gICAgICAgIGNvbnN0IHppcHBlZEJhc2U2NCA9ICdVRXNEQkFvQUFBQUFBTGx6azBvQUFBQUFBQUFBQUFBQUFBQUpBQkFBZFc1NmFYQndaV1F2VlZnTUFOQk8rVmpPMXZkWTlRRVVBRkJMQXdRS0FBQUFBQURBYzVOS0FBQUFBQUFBQUFBQUFBQUFFZ0FRQUhWdWVtbHdjR1ZrTDNSbGMzUXRaR2x5TDFWWURBRFFUdmxZMTliM1dQVUJGQUJRU3dNRUZBQUlBQWdBd25PVFNnQUFBQUFBQUFBQUFBQUFBQmNBRUFCMWJucHBjSEJsWkM5MFpYTjBMV1JwY2k5aExuUjRkRlZZREFDRFR2bFkzTmIzV1BVQkZBRHpTTTNKeVZjSXp5L0tTUUVBVUVzSENGYXhGMG9OQUFBQUN3QUFBRkJMQXdRVUFBZ0FDQURFYzVOS0FBQUFBQUFBQUFBQUFBQUFGd0FRQUhWdWVtbHdjR1ZrTDNSbGMzUXRaR2x5TDJJdWRIaDBWVmdNQUlOTytWamYxdmRZOVFFVUFIUEx6MWR3U2l3Q0FGQkxCd2hJZnJaSkNRQUFBQWNBQUFCUVN3RUNGUU1LQUFBQUFBQzVjNU5LQUFBQUFBQUFBQUFBQUFBQUNRQU1BQUFBQUFBQUFBQkE3VUVBQUFBQWRXNTZhWEJ3WldRdlZWZ0lBTkJPK1ZqTzF2ZFlVRXNCQWhVRENnQUFBQUFBd0hPVFNnQUFBQUFBQUFBQUFBQUFBQklBREFBQUFBQUFBQUFBUU8xQk53QUFBSFZ1ZW1sd2NHVmtMM1JsYzNRdFpHbHlMMVZZQ0FEUVR2bFkxOWIzV0ZCTEFRSVZBeFFBQ0FBSUFNSnprMHBXc1JkS0RRQUFBQXNBQUFBWEFBd0FBQUFBQUFBQUFFQ2tnWGNBQUFCMWJucHBjSEJsWkM5MFpYTjBMV1JwY2k5aExuUjRkRlZZQ0FDRFR2bFkzTmIzV0ZCTEFRSVZBeFFBQ0FBSUFNUnprMHBJZnJaSkNRQUFBQWNBQUFBWEFBd0FBQUFBQUFBQUFFQ2tnZGtBQUFCMWJucHBjSEJsWkM5MFpYTjBMV1JwY2k5aUxuUjRkRlZZQ0FDRFR2bFkzOWIzV0ZCTEJRWUFBQUFBQkFBRUFERUJBQUEzQVFBQUFBQT0nO1xuICAgICAgICB6aXBwZWRGaWxlUGF0aCA9IHBhdGgucmVzb2x2ZSh0bXBSb290LCAnemlwcGVkLnppcCcpO1xuICAgICAgICBhd2FpdCBmcy53cml0ZUZpbGUoemlwcGVkRmlsZVBhdGgsIHppcHBlZEJhc2U2NCwgJ2Jhc2U2NCcpO1xuICAgICAgICBhd2FpdCB6aXAuZXh0cmFjdEFsbFRvKHppcHBlZEZpbGVQYXRoLCBhc3NldHNQYXRoLCBvcHRpb25zKTtcbiAgICAgIH0pO1xuXG4gICAgICBhZnRlckVhY2goYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBmb3IgKGNvbnN0IHRtcFBhdGggb2YgW2Fzc2V0c1BhdGgsIHRtcFJvb3RdKSB7XG4gICAgICAgICAgaWYgKCFhd2FpdCBmcy5leGlzdHModG1wUGF0aCkpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBhd2FpdCBmcy5yaW1yYWYodG1wUGF0aCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBkZXNjcmliZSgnZXh0cmFjdEFsbFRvKCknLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGl0KCdzaG91bGQgZXh0cmFjdCBjb250ZW50cyBvZiBhIC56aXAgZmlsZSB0byBhIGRpcmVjdG9yeScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBhd2FpdCBmcy5yZWFkRmlsZShwYXRoLnJlc29sdmUoYXNzZXRzUGF0aCwgJ3VuemlwcGVkJywgJ3Rlc3QtZGlyJywgJ2EudHh0JyksIHtlbmNvZGluZzogJ3V0ZjgnfSkuc2hvdWxkLmV2ZW50dWFsbHkuZXF1YWwoJ0hlbGxvIFdvcmxkJyk7XG4gICAgICAgICAgYXdhaXQgZnMucmVhZEZpbGUocGF0aC5yZXNvbHZlKGFzc2V0c1BhdGgsICd1bnppcHBlZCcsICd0ZXN0LWRpcicsICdiLnR4dCcpLCB7ZW5jb2Rpbmc6ICd1dGY4J30pLnNob3VsZC5ldmVudHVhbGx5LmVxdWFsKCdGb28gQmFyJyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGRlc2NyaWJlKCdhc3NlcnRWYWxpZFppcCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaXQoJ3Nob3VsZCBub3QgdGhyb3cgYW4gZXJyb3IgaWYgYSB2YWxpZCBaSVAgZmlsZSBpcyBwYXNzZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgYXdhaXQgemlwLmFzc2VydFZhbGlkWmlwKHppcHBlZEZpbGVQYXRoKS5zaG91bGQuZXZlbnR1YWxseS5iZS5mdWxmaWxsZWQ7XG4gICAgICAgIH0pO1xuICAgICAgICBpdCgnc2hvdWxkIHRocm93IGFuIGVycm9yIGlmIHRoZSBmaWxlIGRvZXMgbm90IGV4aXN0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGF3YWl0IHppcC5hc3NlcnRWYWxpZFppcCgnYmxhYmxhJykuc2hvdWxkLmV2ZW50dWFsbHkuYmUucmVqZWN0ZWQ7XG4gICAgICAgIH0pO1xuICAgICAgICBpdCgnc2hvdWxkIHRocm93IGFuIGVycm9yIGlmIHRoZSBmaWxlIGlzIGludmFsaWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgYXdhaXQgemlwLmFzc2VydFZhbGlkWmlwKHBhdGgucmVzb2x2ZShhc3NldHNQYXRoLCAndW56aXBwZWQnLCAndGVzdC1kaXInLCAnYS50eHQnKSkuc2hvdWxkLmV2ZW50dWFsbHkuYmUucmVqZWN0ZWQ7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGRlc2NyaWJlKCdyZWFkRW50cmllcygpJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBleHBlY3RlZEVudHJpZXMgPSBbXG4gICAgICAgICAge25hbWU6ICd1bnppcHBlZC8nfSxcbiAgICAgICAgICB7bmFtZTogJ3VuemlwcGVkL3Rlc3QtZGlyLyd9LFxuICAgICAgICAgIHtuYW1lOiAndW56aXBwZWQvdGVzdC1kaXIvYS50eHQnLCBjb250ZW50czogJ0hlbGxvIFdvcmxkJ30sXG4gICAgICAgICAge25hbWU6ICd1bnppcHBlZC90ZXN0LWRpci9iLnR4dCcsIGNvbnRlbnRzOiAnRm9vIEJhcid9LFxuICAgICAgICBdO1xuXG4gICAgICAgIGl0KCdzaG91bGQgaXRlcmF0ZSBlbnRyaWVzIChkaXJlY3RvcmllcyBhbmQgZmlsZXMpIG9mIHppcCBmaWxlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGxldCBpID0gMDtcbiAgICAgICAgICBhd2FpdCB6aXAucmVhZEVudHJpZXMoemlwcGVkRmlsZVBhdGgsIGFzeW5jICh7ZW50cnksIGV4dHJhY3RFbnRyeVRvfSkgPT4ge1xuICAgICAgICAgICAgZW50cnkuZmlsZU5hbWUuc2hvdWxkLmVxdWFsKGV4cGVjdGVkRW50cmllc1tpXS5uYW1lKTtcblxuICAgICAgICAgICAgLy8gSWYgaXQncyBhIGZpbGUsIHRlc3QgdGhhdCB3ZSBjYW4gZXh0cmFjdCBpdCB0byBhIHRlbXBvcmFyeSBkaXJlY3RvcnkgYW5kIHRoYXQgdGhlIGNvbnRlbnRzIGFyZSBjb3JyZWN0XG4gICAgICAgICAgICBpZiAoZXhwZWN0ZWRFbnRyaWVzW2ldLmNvbnRlbnRzKSB7XG4gICAgICAgICAgICAgIGF3YWl0IGV4dHJhY3RFbnRyeVRvKHRtcFJvb3QpO1xuICAgICAgICAgICAgICBhd2FpdCBmcy5yZWFkRmlsZShwYXRoLnJlc29sdmUodG1wUm9vdCwgZW50cnkuZmlsZU5hbWUpLCB7XG4gICAgICAgICAgICAgICAgZmxhZ3M6ICdyJyxcbiAgICAgICAgICAgICAgICBlbmNvZGluZzogJ3V0ZjgnXG4gICAgICAgICAgICAgIH0pLnNob3VsZC5ldmVudHVhbGx5LmVxdWFsKGV4cGVjdGVkRW50cmllc1tpXS5jb250ZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpKys7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGl0KCdzaG91bGQgc3RvcCBpdGVyYXRpbmcgemlwRmlsZSBpZiBvbkVudHJ5IGNhbGxiYWNrIHJldHVybnMgZmFsc2UnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgbGV0IGkgPSAwO1xuICAgICAgICAgIGF3YWl0IHppcC5yZWFkRW50cmllcyh6aXBwZWRGaWxlUGF0aCwgYXN5bmMgKCkgPT4geyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIHJlcXVpcmUtYXdhaXRcbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBpLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCBiZSByZWplY3RlZCBpZiBpdCB1c2VzIGEgbm9uLXppcCBmaWxlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGxldCBwcm9taXNlID0gemlwLnJlYWRFbnRyaWVzKHBhdGgucmVzb2x2ZShhc3NldHNQYXRoLCAndW56aXBwZWQnLCAndGVzdC1kaXInLCAnYS50eHQnKSwgYXN5bmMgKCkgPT4ge30pO1xuICAgICAgICAgIGF3YWl0IHByb21pc2Uuc2hvdWxkLmV2ZW50dWFsbHkuYmUucmVqZWN0ZWQ7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGRlc2NyaWJlKCd0b0luTWVtb3J5WmlwKCknLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGl0KCdzaG91bGQgY29udmVydCBhIGxvY2FsIGZpbGUgdG8gYW4gaW4tbWVtb3J5IHppcCBidWZmZXInLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgLy8gQ29udmVydCBkaXJlY3RvcnkgdG8gaW4tbWVtb3J5IGJ1ZmZlclxuICAgICAgICAgIGNvbnN0IHRlc3RGb2xkZXIgPSBwYXRoLnJlc29sdmUoYXNzZXRzUGF0aCwgJ3VuemlwcGVkJyk7XG4gICAgICAgICAgY29uc3QgYnVmZmVyID0gYXdhaXQgemlwLnRvSW5NZW1vcnlaaXAodGVzdEZvbGRlcik7XG4gICAgICAgICAgQnVmZmVyLmlzQnVmZmVyKGJ1ZmZlcikuc2hvdWxkLmJlLnRydWU7XG5cbiAgICAgICAgICAvLyBXcml0ZSB0aGUgYnVmZmVyIHRvIGEgemlwIGZpbGVcbiAgICAgICAgICBhd2FpdCBmcy53cml0ZUZpbGUocGF0aC5yZXNvbHZlKHRtcFJvb3QsICd0ZXN0LnppcCcpLCBidWZmZXIpO1xuXG4gICAgICAgICAgLy8gVW56aXAgdGhlIGZpbGUgYW5kIHRlc3QgdGhhdCBpdCBoYXMgdGhlIHNhbWUgY29udGVudHMgYXMgdGhlIGRpcmVjdG9yeSB0aGF0IHdhcyB6aXBwZWRcbiAgICAgICAgICBhd2FpdCB6aXAuZXh0cmFjdEFsbFRvKHBhdGgucmVzb2x2ZSh0bXBSb290LCAndGVzdC56aXAnKSwgcGF0aC5yZXNvbHZlKHRtcFJvb3QsICdvdXRwdXQnKSwge1xuICAgICAgICAgICAgZmlsZU5hbWVzRW5jb2Rpbmc6ICd1dGY4J1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGF3YWl0IGZzLnJlYWRGaWxlKHBhdGgucmVzb2x2ZSh0bXBSb290LCAnb3V0cHV0JywgJ3Rlc3QtZGlyJywgJ2EudHh0JyksIHtcbiAgICAgICAgICAgIGVuY29kaW5nOiAndXRmOCdcbiAgICAgICAgICB9KS5zaG91bGQuZXZlbnR1YWxseS5lcXVhbCgnSGVsbG8gV29ybGQnKTtcbiAgICAgICAgICBhd2FpdCBmcy5yZWFkRmlsZShwYXRoLnJlc29sdmUodG1wUm9vdCwgJ291dHB1dCcsICd0ZXN0LWRpcicsICdiLnR4dCcpLCB7XG4gICAgICAgICAgICBlbmNvZGluZzogJ3V0ZjgnXG4gICAgICAgICAgfSkuc2hvdWxkLmV2ZW50dWFsbHkuZXF1YWwoJ0ZvbyBCYXInKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCBjb252ZXJ0IGEgbG9jYWwgZm9sZGVyIHRvIGFuIGluLW1lbW9yeSBiYXNlNjQtZW5jb2RlZCB6aXAgYnVmZmVyJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IHRlc3RGb2xkZXIgPSBwYXRoLnJlc29sdmUoYXNzZXRzUGF0aCwgJ3VuemlwcGVkJyk7XG4gICAgICAgICAgY29uc3QgYnVmZmVyID0gYXdhaXQgemlwLnRvSW5NZW1vcnlaaXAodGVzdEZvbGRlciwge1xuICAgICAgICAgICAgZW5jb2RlVG9CYXNlNjQ6IHRydWUsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBhd2FpdCBmcy53cml0ZUZpbGUocGF0aC5yZXNvbHZlKHRtcFJvb3QsICd0ZXN0LnppcCcpLCBCdWZmZXIuZnJvbShidWZmZXIudG9TdHJpbmcoKSwgJ2Jhc2U2NCcpKTtcblxuICAgICAgICAgIC8vIFVuemlwIHRoZSBmaWxlIGFuZCB0ZXN0IHRoYXQgaXQgaGFzIHRoZSBzYW1lIGNvbnRlbnRzIGFzIHRoZSBkaXJlY3RvcnkgdGhhdCB3YXMgemlwcGVkXG4gICAgICAgICAgYXdhaXQgemlwLmV4dHJhY3RBbGxUbyhwYXRoLnJlc29sdmUodG1wUm9vdCwgJ3Rlc3QuemlwJyksIHBhdGgucmVzb2x2ZSh0bXBSb290LCAnb3V0cHV0JykpO1xuICAgICAgICAgIGF3YWl0IGZzLnJlYWRGaWxlKHBhdGgucmVzb2x2ZSh0bXBSb290LCAnb3V0cHV0JywgJ3Rlc3QtZGlyJywgJ2EudHh0JyksIHtcbiAgICAgICAgICAgIGVuY29kaW5nOiAndXRmOCdcbiAgICAgICAgICB9KS5zaG91bGQuZXZlbnR1YWxseS5lcXVhbCgnSGVsbG8gV29ybGQnKTtcbiAgICAgICAgICBhd2FpdCBmcy5yZWFkRmlsZShwYXRoLnJlc29sdmUodG1wUm9vdCwgJ291dHB1dCcsICd0ZXN0LWRpcicsICdiLnR4dCcpLCB7XG4gICAgICAgICAgICBlbmNvZGluZzogJ3V0ZjgnXG4gICAgICAgICAgfSkuc2hvdWxkLmV2ZW50dWFsbHkuZXF1YWwoJ0ZvbyBCYXInKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCBiZSByZWplY3RlZCBpZiB1c2UgYSBiYWQgcGF0aCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBhd2FpdCB6aXAudG9Jbk1lbW9yeVppcChwYXRoLnJlc29sdmUoYXNzZXRzUGF0aCwgJ2JhZF9wYXRoJykpXG4gICAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvbm8gc3VjaC9pKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCBiZSByZWplY3RlZCBpZiBtYXggc2l6ZSBpcyBleGNlZWRlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBjb25zdCB0ZXN0Rm9sZGVyID0gcGF0aC5yZXNvbHZlKGFzc2V0c1BhdGgsICd1bnppcHBlZCcpO1xuICAgICAgICAgIGF3YWl0IHppcC50b0luTWVtb3J5WmlwKHRlc3RGb2xkZXIsIHtcbiAgICAgICAgICAgIG1heFNpemU6IDEsXG4gICAgICAgICAgfSkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvbXVzdCBub3QgYmUgZ3JlYXRlci8pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBkZXNjcmliZSgnX2V4dHJhY3RFbnRyeVRvKCknLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxldCBlbnRyeSwgbW9ja1ppcEZpbGUsIG1vY2taaXBTdHJlYW07XG4gICAgICAgIGJlZm9yZUVhY2goYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGVudHJ5ID0ge2ZpbGVOYW1lOiBwYXRoLnJlc29sdmUoYXdhaXQgdGVtcERpci5vcGVuRGlyKCksICd0ZW1wJywgJ2ZpbGUnKX07XG4gICAgICAgICAgbW9ja1ppcFN0cmVhbSA9IG5ldyBNb2NrUmVhZFdyaXRlU3RyZWFtKCk7XG4gICAgICAgICAgbW9ja1ppcEZpbGUgPSB7XG4gICAgICAgICAgICBvcGVuUmVhZFN0cmVhbTogKGVudHJ5LCBjYikgPT4gY2IobnVsbCwgbW9ja1ppcFN0cmVhbSksIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgcHJvbWlzZS9wcmVmZXItYXdhaXQtdG8tY2FsbGJhY2tzXG4gICAgICAgICAgfTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCBiZSByZWplY3RlZCBpZiB6aXAgc3RyZWFtIGVtaXRzIGFuIGVycm9yJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIG1vY2taaXBTdHJlYW0ucGlwZSA9ICgpID0+IHtcbiAgICAgICAgICAgIG1vY2taaXBTdHJlYW0uZW1pdCgnZXJyb3InLCBuZXcgRXJyb3IoJ3ppcCBzdHJlYW0gZXJyb3InKSk7XG4gICAgICAgICAgfTtcbiAgICAgICAgICBhd2FpdCB6aXAuX2V4dHJhY3RFbnRyeVRvKG1vY2taaXBGaWxlLCBlbnRyeSkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnemlwIHN0cmVhbSBlcnJvcicpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpdCgnc2hvdWxkIGJlIHJlamVjdGVkIGlmIHdyaXRlIHN0cmVhbSBlbWl0cyBhbiBlcnJvcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBtb2NrWmlwU3RyZWFtLnBpcGUgPSAod3JpdGVTdHJlYW0pID0+IHtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtLmVtaXQoJ2Vycm9yJywgbmV3IEVycm9yKCd3cml0ZSBzdHJlYW0gZXJyb3InKSk7XG4gICAgICAgICAgICBtb2NrWmlwU3RyZWFtLmVuZCgpO1xuICAgICAgICAgICAgd3JpdGVTdHJlYW0uZW5kKCk7XG4gICAgICAgICAgfTtcbiAgICAgICAgICBhd2FpdCB6aXAuX2V4dHJhY3RFbnRyeVRvKG1vY2taaXBGaWxlLCBlbnRyeSkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnd3JpdGUgc3RyZWFtIGVycm9yJyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGRlc2NyaWJlKCd0b0FyY2hpdmUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGl0KCdzaG91bGQgemlwIGFsbCBmaWxlcyBpbnRvIGFuIGFyY2hpdmUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgY29uc3QgdGVzdEZvbGRlciA9IHBhdGgucmVzb2x2ZShhc3NldHNQYXRoLCAndW56aXBwZWQnKTtcbiAgICAgICAgICBjb25zdCBkc3RQYXRoID0gcGF0aC5yZXNvbHZlKHRtcFJvb3QsICd0ZXN0LnppcCcpO1xuICAgICAgICAgIGF3YWl0IHppcC50b0FyY2hpdmUoZHN0UGF0aCwge1xuICAgICAgICAgICAgY3dkOiB0ZXN0Rm9sZGVyLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gVW56aXAgdGhlIGZpbGUgYW5kIHRlc3QgdGhhdCBpdCBoYXMgdGhlIHNhbWUgY29udGVudHMgYXMgdGhlIGRpcmVjdG9yeSB0aGF0IHdhcyB6aXBwZWRcbiAgICAgICAgICBhd2FpdCB6aXAuZXh0cmFjdEFsbFRvKGRzdFBhdGgsIHBhdGgucmVzb2x2ZSh0bXBSb290LCAnb3V0cHV0JykpO1xuICAgICAgICAgIGF3YWl0IGZzLnJlYWRGaWxlKHBhdGgucmVzb2x2ZSh0bXBSb290LCAnb3V0cHV0JywgJ3Rlc3QtZGlyJywgJ2EudHh0JyksIHtcbiAgICAgICAgICAgIGVuY29kaW5nOiAndXRmOCdcbiAgICAgICAgICB9KS5zaG91bGQuZXZlbnR1YWxseS5lcXVhbCgnSGVsbG8gV29ybGQnKTtcbiAgICAgICAgICBhd2FpdCBmcy5yZWFkRmlsZShwYXRoLnJlc29sdmUodG1wUm9vdCwgJ291dHB1dCcsICd0ZXN0LWRpcicsICdiLnR4dCcpLCB7XG4gICAgICAgICAgICBlbmNvZGluZzogJ3V0ZjgnXG4gICAgICAgICAgfSkuc2hvdWxkLmV2ZW50dWFsbHkuZXF1YWwoJ0ZvbyBCYXInKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuXG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCd1bmljb2RlIGZpbGVuYW1lIGhhbmRsaW5nJywgZnVuY3Rpb24gKCkge1xuICAgIGxldCB6aXBwZWRGaWxlUGF0aCwgYXNzZXRzUGF0aCwgdG1wUm9vdDtcblxuICAgIGJlZm9yZUVhY2goYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXRzUGF0aCA9IGF3YWl0IHRlbXBEaXIub3BlbkRpcigpO1xuICAgICAgdG1wUm9vdCA9IGF3YWl0IHRlbXBEaXIub3BlbkRpcigpO1xuXG4gICAgICBjb25zdCB6aXBwZWRCYXNlNjQgPSAnVUVzREJCUUFDQUFJQUJGOC9FWUFBQUFBQUFBQUFCb0FBQUFUQUNBQWEyRnVhbWt0NXEyajVMaVc1TGlWTG1Gd2NGVlVEUUFIQWdPNFZWcFgrR0JaVi9oZ2RYZ0xBQUVFOVFFQUFBUVVBQUFBSzhuSUxGWUFvcno4RW9XaTFNU2NuRXFGeER5RnhJSUNMZ0JRU3djSVI5M2pQaG9BQUFBYUFBQUFVRXNCQWhRREZBQUlBQWdBRVh6OFJrZmQ0ejRhQUFBQUdnQUFBQk1BSUFBQUFBQUFBQUFBQUtTQkFBQUFBR3RoYm1wcExlYXRvK1M0bHVTNGxTNWhjSEJWVkEwQUJ3SUR1RlZhVi9oZ1dWZjRZSFY0Q3dBQkJQVUJBQUFFRkFBQUFGQkxCUVlBQUFBQUFRQUJBR0VBQUFCN0FBQUFBQUE9JztcbiAgICAgIHppcHBlZEZpbGVQYXRoID0gcGF0aC5yZXNvbHZlKHRtcFJvb3QsICd6aXBwZWQuemlwJyk7XG4gICAgICBhd2FpdCBmcy53cml0ZUZpbGUoemlwcGVkRmlsZVBhdGgsIHppcHBlZEJhc2U2NCwgJ2Jhc2U2NCcpO1xuICAgICAgYXdhaXQgemlwLmV4dHJhY3RBbGxUbyh6aXBwZWRGaWxlUGF0aCwgYXNzZXRzUGF0aCwge3VzZVN5c3RlbVVuemlwOiB0cnVlfSk7XG4gICAgfSk7XG5cbiAgICBhZnRlckVhY2goYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgZm9yIChjb25zdCB0bXBQYXRoIG9mIFthc3NldHNQYXRoLCB0bXBSb290XSkge1xuICAgICAgICBpZiAoIWF3YWl0IGZzLmV4aXN0cyh0bXBQYXRoKSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IGZzLnJpbXJhZih0bXBQYXRoKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0YWluIHRoZSBwcm9wZXIgZmlsZW5hbWVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXhwZWN0ZWRQYXRoID0gcGF0aC5qb2luKGFzc2V0c1BhdGgsICdrYW5qaS3mraPkuJbkuJUuYXBwJyk7XG4gICAgICAvLyB3ZSBjYW5ub3QgdXNlIHRoZSBgc2hvdWxkYCBzeW50YXggYmVjYXVzZSBgZnMuZXhpc3RzYCByZXNvbHZlcyB0byBhIHByaW1pdGl2ZSAoYm9vbGVhbilcbiAgICAgIGlmICghYXdhaXQgZnMuZXhpc3RzKGV4cGVjdGVkUGF0aCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IGNoYWkuQXNzZXJ0aW9uRXJyb3IoYEV4cGVjdGVkICR7ZXhwZWN0ZWRQYXRofSB0byBleGlzdCwgYnV0IGl0IGRvZXMgbm90YCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXSwiZmlsZSI6InRlc3QvemlwLWUyZS1zcGVjcy5qcyIsInNvdXJjZVJvb3QiOiIuLi8uLiJ9
|
package/index.js
CHANGED
|
@@ -1,28 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import * as system from './lib/system';
|
|
3
|
-
import * as util from './lib/util';
|
|
4
|
-
import * as fsIndex from './lib/fs';
|
|
5
|
-
import * as net from './lib/net';
|
|
6
|
-
import * as plist from './lib/plist';
|
|
7
|
-
import * as mkdirpIndex from './lib/mkdirp';
|
|
8
|
-
import * as logger from './lib/logging';
|
|
9
|
-
import * as process from './lib/process';
|
|
10
|
-
import * as zip from './lib/zip';
|
|
11
|
-
import * as imageUtil from './lib/image-util';
|
|
12
|
-
import * as mjpeg from './lib/mjpeg';
|
|
13
|
-
import * as node from './lib/node';
|
|
14
|
-
import * as timing from './lib/timing';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const { fs } = fsIndex;
|
|
18
|
-
const { cancellableDelay } = util;
|
|
19
|
-
const { mkdirp } = mkdirpIndex;
|
|
20
|
-
|
|
21
|
-
export {
|
|
22
|
-
tempDir, system, util, fs, cancellableDelay, plist, mkdirp, logger, process,
|
|
23
|
-
zip, imageUtil, net, mjpeg, node, timing,
|
|
24
|
-
};
|
|
25
|
-
export default {
|
|
26
|
-
tempDir, system, util, fs, cancellableDelay, plist, mkdirp, logger, process,
|
|
27
|
-
zip, imageUtil, net, mjpeg, node, timing,
|
|
28
|
-
};
|
|
1
|
+
module.exports = require('./build/lib');
|
package/lib/image-util.js
CHANGED
|
@@ -8,6 +8,10 @@ import log from './logger';
|
|
|
8
8
|
import { requirePackage } from './node';
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
const OCV_OLD = 'opencv4nodejs';
|
|
12
|
+
const OCV_NEW = '@u4/opencv4nodejs';
|
|
13
|
+
|
|
14
|
+
|
|
11
15
|
const { MIME_JPEG, MIME_PNG, MIME_BMP } = Jimp;
|
|
12
16
|
let cv = null;
|
|
13
17
|
|
|
@@ -127,16 +131,20 @@ async function initOpenCV () {
|
|
|
127
131
|
}
|
|
128
132
|
|
|
129
133
|
log.debug(`Initializing opencv`);
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
+
for (const ocvPackage of [OCV_OLD, OCV_NEW]) {
|
|
135
|
+
try {
|
|
136
|
+
log.debug(`Attempting to load '${ocvPackage}'`);
|
|
137
|
+
cv = await requirePackage(ocvPackage);
|
|
138
|
+
break;
|
|
139
|
+
} catch (err) {
|
|
140
|
+
log.warn(`Unable to load '${ocvPackage}': ${err.message}`);
|
|
141
|
+
}
|
|
134
142
|
}
|
|
135
143
|
|
|
136
144
|
if (!cv) {
|
|
137
|
-
throw new Error(`
|
|
138
|
-
`Please install
|
|
139
|
-
'Read https://github.com/
|
|
145
|
+
throw new Error(`An opencv node module is required to use OpenCV features. ` +
|
|
146
|
+
`Please install one first (e.g., 'npm i -g ${OCV_NEW}') and restart Appium. ` +
|
|
147
|
+
'Read https://github.com/UrielCh/opencv4nodejs#how-to-install for more details on this topic.');
|
|
140
148
|
}
|
|
141
149
|
}
|
|
142
150
|
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as tempDir from './tempdir';
|
|
2
|
+
import * as system from './system';
|
|
3
|
+
import * as util from './util';
|
|
4
|
+
import * as fsIndex from './fs';
|
|
5
|
+
import * as net from './net';
|
|
6
|
+
import * as plist from './plist';
|
|
7
|
+
import * as mkdirpIndex from './mkdirp';
|
|
8
|
+
import * as logger from './logging';
|
|
9
|
+
import * as process from './process';
|
|
10
|
+
import * as zip from './zip';
|
|
11
|
+
import * as imageUtil from './image-util';
|
|
12
|
+
import * as mjpeg from './mjpeg';
|
|
13
|
+
import * as node from './node';
|
|
14
|
+
import * as timing from './timing';
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
const { fs } = fsIndex;
|
|
18
|
+
const { cancellableDelay } = util;
|
|
19
|
+
const { mkdirp } = mkdirpIndex;
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
tempDir, system, util, fs, cancellableDelay, plist, mkdirp, logger, process,
|
|
23
|
+
zip, imageUtil, net, mjpeg, node, timing,
|
|
24
|
+
};
|
|
25
|
+
export default {
|
|
26
|
+
tempDir, system, util, fs, cancellableDelay, plist, mkdirp, logger, process,
|
|
27
|
+
zip, imageUtil, net, mjpeg, node, timing,
|
|
28
|
+
};
|
package/lib/log-internal.js
CHANGED
|
@@ -103,7 +103,7 @@ class SecureValuesPreprocessor {
|
|
|
103
103
|
/**
|
|
104
104
|
* Loads rules from the given JSON file
|
|
105
105
|
*
|
|
106
|
-
* @param {string|
|
|
106
|
+
* @param {string|string[]|Rule[]>} source The full path to the JSON file containing secure
|
|
107
107
|
* values replacement rules or the rules themselves represented as an array
|
|
108
108
|
* @throws {Error} If the format of the source file is invalid or
|
|
109
109
|
* it does not exist
|
package/lib/logging.js
CHANGED
|
@@ -117,7 +117,7 @@ function getLogger (prefix = null) {
|
|
|
117
117
|
* appear in Appium logs.
|
|
118
118
|
* Each call to this method replaces the previously loaded rules if any existed.
|
|
119
119
|
*
|
|
120
|
-
* @param {string} rulesJsonPath The full path to the JSON file containing
|
|
120
|
+
* @param {string|string[]|Rule[]} rulesJsonPath The full path to the JSON file containing
|
|
121
121
|
* the replacement rules. Each rule could either be a string to be replaced
|
|
122
122
|
* or an object with predefined properties. See the `Rule` type definition in
|
|
123
123
|
* `log-internals.js` to get more details on its format.
|
package/lib/net.js
CHANGED
|
@@ -9,6 +9,7 @@ import Timer from './timing';
|
|
|
9
9
|
import axios from 'axios';
|
|
10
10
|
import FormData from 'form-data';
|
|
11
11
|
|
|
12
|
+
const DEFAULT_TIMEOUT_MS = 4 * 60 * 1000;
|
|
12
13
|
|
|
13
14
|
function toAxiosAuth (auth) {
|
|
14
15
|
if (!_.isPlainObject(auth)) {
|
|
@@ -25,7 +26,7 @@ function toAxiosAuth (auth) {
|
|
|
25
26
|
async function uploadFileToHttp (localFileStream, parsedUri, uploadOptions = {}) {
|
|
26
27
|
const {
|
|
27
28
|
method = 'POST',
|
|
28
|
-
timeout =
|
|
29
|
+
timeout = DEFAULT_TIMEOUT_MS,
|
|
29
30
|
headers,
|
|
30
31
|
auth,
|
|
31
32
|
fileFieldName = 'file',
|
|
@@ -128,7 +129,7 @@ async function uploadFileToFtp (localFileStream, parsedUri, uploadOptions = {})
|
|
|
128
129
|
* (e.g. timings and speed)
|
|
129
130
|
* @property {string} method [POST] - The HTTP method used for file upload
|
|
130
131
|
* @property {AuthCredentials} auth
|
|
131
|
-
* @property {number} timeout [
|
|
132
|
+
* @property {number} timeout [240000] - The actual request timeout in milliseconds
|
|
132
133
|
* @property {Object} headers - Additional request headers mapping
|
|
133
134
|
* @property {?string} fileFieldName [file] - The name of the form field containing the file
|
|
134
135
|
* content to be uploaded. Any falsy value make the request to use non-multipart upload
|
|
@@ -186,7 +187,7 @@ async function uploadFile (localPath, remoteUri, uploadOptions = {}) {
|
|
|
186
187
|
* @property {boolean} isMetered [true] - Whether to log the actual download performance
|
|
187
188
|
* (e.g. timings and speed)
|
|
188
189
|
* @property {AuthCredentials} auth
|
|
189
|
-
* @property {number} timeout [
|
|
190
|
+
* @property {number} timeout [240000] - The actual request timeout in milliseconds
|
|
190
191
|
* @property {Object} headers - Request headers mapping
|
|
191
192
|
*/
|
|
192
193
|
|
|
@@ -202,7 +203,7 @@ async function downloadFile (remoteUrl, dstPath, downloadOptions = {}) {
|
|
|
202
203
|
const {
|
|
203
204
|
isMetered = true,
|
|
204
205
|
auth,
|
|
205
|
-
timeout =
|
|
206
|
+
timeout = DEFAULT_TIMEOUT_MS,
|
|
206
207
|
headers,
|
|
207
208
|
} = downloadOptions;
|
|
208
209
|
|
package/lib/zip.js
CHANGED
|
@@ -7,6 +7,7 @@ import path from 'path';
|
|
|
7
7
|
import { mkdirp } from '../lib/mkdirp';
|
|
8
8
|
import stream from 'stream';
|
|
9
9
|
import fs from './fs';
|
|
10
|
+
import { isWindows } from './system';
|
|
10
11
|
import { Base64Encode } from 'base64-stream';
|
|
11
12
|
import { toReadableSizeString, GiB } from './util';
|
|
12
13
|
import Timer from './timing';
|
|
@@ -173,13 +174,7 @@ class ZipExtractor {
|
|
|
173
174
|
* For ZIP archives created on MacOS it is usually expected to be `utf8`.
|
|
174
175
|
* By default it is autodetected based on the entry metadata and is only needed to be set explicitly
|
|
175
176
|
* if the particular archive does not comply to the standards, which leads to corrupted file names
|
|
176
|
-
* after extraction.
|
|
177
|
-
* @property {?number} defaultDirMode [0o755] The default permissions for extracted folders. It is only
|
|
178
|
-
* applied when the extractor is unable to retrieve this value for a directory from the archive
|
|
179
|
-
* metadata.
|
|
180
|
-
* @property {?number} defaultFileMode [0o644] The default permissions for extracted files. It is only
|
|
181
|
-
* applied when the extractor is unable to retrieve this value for a file from the archive
|
|
182
|
-
* metadata.
|
|
177
|
+
* after extraction. Only applicable if system unzip binary is NOT being used.
|
|
183
178
|
* @property {?boolean} useSystemUnzip [false] If true, attempt to use system unzip; if this fails,
|
|
184
179
|
* fallback to the JS unzip implementation.
|
|
185
180
|
*/
|
|
@@ -214,22 +209,43 @@ async function extractAllTo (zipFilePath, destDir, opts = {}) {
|
|
|
214
209
|
}
|
|
215
210
|
|
|
216
211
|
/**
|
|
217
|
-
* Executes system unzip (e.g., `/usr/bin/unzip`).
|
|
212
|
+
* Executes system unzip (e.g., `/usr/bin/unzip`). If available, it is
|
|
218
213
|
* significantly faster than the JS implementation.
|
|
219
|
-
*
|
|
214
|
+
* By default all files in the destDir get overridden if already exist.
|
|
215
|
+
*
|
|
220
216
|
* @param {string} zipFilePath The full path to the source ZIP file
|
|
221
|
-
* @param {string} destDir The full path to the destination folder
|
|
217
|
+
* @param {string} destDir The full path to the destination folder.
|
|
218
|
+
* This folder is expected to already exist before extracting the archive.
|
|
222
219
|
*/
|
|
223
220
|
async function extractWithSystemUnzip (zipFilePath, destDir) {
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
'
|
|
232
|
-
|
|
221
|
+
const isWindowsHost = isWindows();
|
|
222
|
+
let executablePath;
|
|
223
|
+
try {
|
|
224
|
+
executablePath = await getExecutablePath(
|
|
225
|
+
isWindowsHost ? 'powershell.exe' : 'unzip'
|
|
226
|
+
);
|
|
227
|
+
} catch (e) {
|
|
228
|
+
throw new Error('Could not find system unzip');
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (isWindowsHost) {
|
|
232
|
+
// on Windows we use PowerShell to unzip files
|
|
233
|
+
await exec(executablePath, [
|
|
234
|
+
'-command', 'Expand-Archive',
|
|
235
|
+
'-LiteralPath', zipFilePath,
|
|
236
|
+
'-DestinationPath', destDir,
|
|
237
|
+
'-Force'
|
|
238
|
+
]);
|
|
239
|
+
} else {
|
|
240
|
+
// -q means quiet (no stdout)
|
|
241
|
+
// -o means overwrite
|
|
242
|
+
// -d is the dest dir
|
|
243
|
+
await exec(executablePath, [
|
|
244
|
+
'-q',
|
|
245
|
+
'-o', zipFilePath,
|
|
246
|
+
'-d', destDir
|
|
247
|
+
]);
|
|
248
|
+
}
|
|
233
249
|
}
|
|
234
250
|
|
|
235
251
|
/**
|
|
@@ -512,21 +528,19 @@ async function toArchive (dstPath, src = {}, opts = {}) {
|
|
|
512
528
|
}
|
|
513
529
|
|
|
514
530
|
/**
|
|
515
|
-
* Finds
|
|
531
|
+
* Finds and memoizes the full path to the given executable.
|
|
532
|
+
* Rejects if it is not found.
|
|
516
533
|
*/
|
|
517
|
-
const
|
|
534
|
+
const getExecutablePath = _.memoize(
|
|
518
535
|
/**
|
|
519
|
-
* @returns {B<string>} Path to
|
|
536
|
+
* @returns {B<string>} Full Path to the executable
|
|
520
537
|
*/
|
|
521
|
-
async ()
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
throw new Error('Could not find system unzip');
|
|
528
|
-
}
|
|
529
|
-
});
|
|
538
|
+
async function getExecutablePath (binaryName) {
|
|
539
|
+
const fullPath = await fs.which(binaryName);
|
|
540
|
+
log.debug(`Found '%s' at '%s'`, binaryName, fullPath);
|
|
541
|
+
return fullPath;
|
|
542
|
+
}
|
|
543
|
+
);
|
|
530
544
|
|
|
531
545
|
export { extractAllTo, readEntries, toInMemoryZip, _extractEntryTo,
|
|
532
546
|
assertValidZip, toArchive };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appium/support",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.55.3",
|
|
4
4
|
"description": "Support libs used across appium packages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"automation",
|
|
@@ -21,29 +21,26 @@
|
|
|
21
21
|
},
|
|
22
22
|
"license": "Apache-2.0",
|
|
23
23
|
"author": "https://github.com/appium",
|
|
24
|
-
"main": "./build/index.js",
|
|
25
|
-
"bin": {},
|
|
26
24
|
"directories": {
|
|
27
25
|
"lib": "lib"
|
|
28
26
|
},
|
|
29
27
|
"files": [
|
|
30
28
|
"index.js",
|
|
31
29
|
"lib",
|
|
32
|
-
"build
|
|
33
|
-
"build/lib"
|
|
30
|
+
"build"
|
|
34
31
|
],
|
|
35
32
|
"dependencies": {
|
|
36
|
-
"@babel/runtime": "7.
|
|
33
|
+
"@babel/runtime": "7.16.3",
|
|
37
34
|
"archiver": "5.3.0",
|
|
38
|
-
"axios": "0.
|
|
35
|
+
"axios": "0.24.0",
|
|
39
36
|
"base64-stream": "1.0.0",
|
|
40
37
|
"bluebird": "3.7.2",
|
|
41
38
|
"bplist-creator": "0.1.0",
|
|
42
|
-
"bplist-parser": "0.3.
|
|
39
|
+
"bplist-parser": "0.3.1",
|
|
43
40
|
"find-root": "1.1.0",
|
|
44
41
|
"form-data": "4.0.0",
|
|
45
42
|
"get-stream": "6.0.1",
|
|
46
|
-
"glob": "7.
|
|
43
|
+
"glob": "7.2.0",
|
|
47
44
|
"jimp": "0.16.1",
|
|
48
45
|
"jsftp": "2.1.3",
|
|
49
46
|
"klaw": "3.0.0",
|
|
@@ -60,16 +57,13 @@
|
|
|
60
57
|
"rimraf": "3.0.2",
|
|
61
58
|
"sanitize-filename": "1.6.3",
|
|
62
59
|
"semver": "7.3.5",
|
|
63
|
-
"shell-quote": "1.7.
|
|
64
|
-
"source-map-support": "0.5.
|
|
60
|
+
"shell-quote": "1.7.3",
|
|
61
|
+
"source-map-support": "0.5.21",
|
|
65
62
|
"teen_process": "1.16.0",
|
|
66
63
|
"uuid": "8.3.2",
|
|
67
64
|
"which": "2.0.2",
|
|
68
65
|
"yauzl": "2.10.0"
|
|
69
66
|
},
|
|
70
|
-
"devDependencies": {
|
|
71
|
-
"@appium/gulp-plugins": "^5.5.3"
|
|
72
|
-
},
|
|
73
67
|
"engines": {
|
|
74
68
|
"node": ">=12",
|
|
75
69
|
"npm": ">=6"
|
|
@@ -78,5 +72,5 @@
|
|
|
78
72
|
"access": "public"
|
|
79
73
|
},
|
|
80
74
|
"homepage": "https://appium.io",
|
|
81
|
-
"gitHead": "
|
|
75
|
+
"gitHead": "ca90a11813546ab4851e5b1f0406f420a53227e6"
|
|
82
76
|
}
|