@appium/support 2.58.0 → 2.59.2
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/console.d.ts +110 -0
- package/build/lib/console.d.ts.map +1 -0
- package/build/lib/console.js +113 -0
- package/build/lib/env.d.ts.map +1 -1
- package/build/lib/env.js +1 -1
- package/build/lib/fs.d.ts.map +1 -1
- package/build/lib/fs.js +1 -1
- package/build/lib/image-util.d.ts.map +1 -1
- package/build/lib/image-util.js +1 -1
- package/build/lib/index.d.ts +3 -1
- package/build/lib/index.js +8 -3
- package/build/lib/log-internal.d.ts.map +1 -1
- package/build/lib/log-internal.js +1 -1
- package/build/lib/logger.d.ts +1 -1
- package/build/lib/logger.d.ts.map +1 -1
- package/build/lib/logger.js +1 -1
- package/build/lib/logging.d.ts +11 -4
- package/build/lib/logging.d.ts.map +1 -1
- package/build/lib/logging.js +7 -6
- package/build/lib/mjpeg.d.ts.map +1 -1
- package/build/lib/mjpeg.js +1 -1
- package/build/lib/mkdirp.js +1 -1
- package/build/lib/net.d.ts +5 -2
- package/build/lib/net.d.ts.map +1 -1
- package/build/lib/net.js +1 -1
- package/build/lib/node.d.ts.map +1 -1
- package/build/lib/node.js +1 -1
- package/build/lib/npm.d.ts.map +1 -1
- package/build/lib/npm.js +1 -1
- package/build/lib/plist.d.ts +1 -1
- package/build/lib/plist.d.ts.map +1 -1
- package/build/lib/plist.js +1 -1
- package/build/lib/process.d.ts.map +1 -1
- package/build/lib/process.js +1 -1
- package/build/lib/system.js +1 -1
- package/build/lib/tempdir.d.ts.map +1 -1
- package/build/lib/tempdir.js +1 -1
- package/build/lib/timing.d.ts.map +1 -1
- package/build/lib/timing.js +1 -1
- package/build/lib/util.d.ts +19 -2
- package/build/lib/util.d.ts.map +1 -1
- package/build/lib/util.js +3 -7
- package/build/lib/zip.d.ts +5 -5
- package/build/lib/zip.d.ts.map +1 -1
- package/build/lib/zip.js +2 -2
- package/build/tsconfig.tsbuildinfo +1 -1
- package/lib/console.js +173 -0
- package/lib/env.js +12 -14
- package/lib/fs.js +87 -62
- package/lib/image-util.js +50 -32
- package/lib/index.js +39 -8
- package/lib/log-internal.js +16 -11
- package/lib/logger.js +1 -1
- package/lib/logging.js +32 -30
- package/lib/mjpeg.js +32 -27
- package/lib/mkdirp.js +3 -3
- package/lib/net.js +60 -52
- package/lib/node.js +22 -17
- package/lib/npm.js +50 -47
- package/lib/plist.js +34 -18
- package/lib/process.js +8 -6
- package/lib/system.js +8 -8
- package/lib/tempdir.js +14 -9
- package/lib/timing.js +12 -15
- package/lib/util.js +121 -72
- package/lib/zip.js +88 -92
- package/package.json +12 -8
package/lib/image-util.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import Jimp from 'jimp';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import {Buffer} from 'buffer';
|
|
4
|
+
import {PNG} from 'pngjs';
|
|
5
5
|
import B from 'bluebird';
|
|
6
6
|
|
|
7
7
|
const BYTES_IN_PIXEL_BLOCK = 4;
|
|
8
8
|
const SCANLINE_FILTER_METHOD = 4;
|
|
9
|
-
const {
|
|
9
|
+
const {MIME_JPEG, MIME_PNG, MIME_BMP} = Jimp;
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Utility function to get a Jimp image object from buffer or base64 data. Jimp
|
|
@@ -17,7 +17,7 @@ const { MIME_JPEG, MIME_PNG, MIME_BMP } = Jimp;
|
|
|
17
17
|
* string
|
|
18
18
|
* @returns {Promise<AppiumJimp>} - the jimp image object
|
|
19
19
|
*/
|
|
20
|
-
async function getJimpImage
|
|
20
|
+
async function getJimpImage(data) {
|
|
21
21
|
return await new B((resolve, reject) => {
|
|
22
22
|
if (!_.isString(data) && !_.isBuffer(data)) {
|
|
23
23
|
return reject(new Error('Must initialize jimp object with string or buffer'));
|
|
@@ -26,21 +26,25 @@ async function getJimpImage (data) {
|
|
|
26
26
|
if (_.isString(data)) {
|
|
27
27
|
data = Buffer.from(data, 'base64');
|
|
28
28
|
}
|
|
29
|
-
new Jimp(
|
|
29
|
+
new Jimp(
|
|
30
|
+
data,
|
|
30
31
|
/**
|
|
31
32
|
* @param {Error?} err
|
|
32
33
|
* @param {AppiumJimp} imgObj
|
|
33
34
|
*/
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
(err, imgObj) => {
|
|
36
|
+
if (err) {
|
|
37
|
+
return reject(err);
|
|
38
|
+
}
|
|
39
|
+
if (!imgObj) {
|
|
40
|
+
return reject(new Error('Could not create jimp image from that data'));
|
|
41
|
+
}
|
|
42
|
+
imgObj.getBuffer = B.promisify(imgObj.getBuffer.bind(imgObj), {
|
|
43
|
+
context: imgObj,
|
|
44
|
+
});
|
|
45
|
+
resolve(imgObj);
|
|
40
46
|
}
|
|
41
|
-
|
|
42
|
-
resolve(imgObj);
|
|
43
|
-
});
|
|
47
|
+
);
|
|
44
48
|
});
|
|
45
49
|
}
|
|
46
50
|
|
|
@@ -51,7 +55,7 @@ async function getJimpImage (data) {
|
|
|
51
55
|
* @param {Region} rect The selected region of image
|
|
52
56
|
* @return {Promise<string>} base64 encoded string of cropped image
|
|
53
57
|
*/
|
|
54
|
-
async function cropBase64Image
|
|
58
|
+
async function cropBase64Image(base64Image, rect) {
|
|
55
59
|
const image = await base64ToImage(base64Image);
|
|
56
60
|
cropImage(image, rect);
|
|
57
61
|
return await imageToBase64(image);
|
|
@@ -63,11 +67,12 @@ async function cropBase64Image (base64Image, rect) {
|
|
|
63
67
|
* @param {string} base64Image The string with base64 encoded image
|
|
64
68
|
* @return {Promise<PNG>} The image object
|
|
65
69
|
*/
|
|
66
|
-
async function base64ToImage
|
|
70
|
+
async function base64ToImage(base64Image) {
|
|
67
71
|
const imageBuffer = Buffer.from(base64Image, 'base64');
|
|
68
72
|
return await new B((resolve, reject) => {
|
|
69
73
|
const image = new PNG({filterType: SCANLINE_FILTER_METHOD});
|
|
70
|
-
image.parse(imageBuffer, (err, image) => {
|
|
74
|
+
image.parse(imageBuffer, (err, image) => {
|
|
75
|
+
// eslint-disable-line promise/prefer-await-to-callbacks
|
|
71
76
|
if (err) {
|
|
72
77
|
return reject(err);
|
|
73
78
|
}
|
|
@@ -82,16 +87,19 @@ async function base64ToImage (base64Image) {
|
|
|
82
87
|
* @param {PNG} image The image object
|
|
83
88
|
* @return {Promise<string>} The string with base64 encoded image
|
|
84
89
|
*/
|
|
85
|
-
async function imageToBase64
|
|
90
|
+
async function imageToBase64(image) {
|
|
86
91
|
return await new B((resolve, reject) => {
|
|
87
92
|
const chunks = [];
|
|
88
|
-
image
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
image
|
|
94
|
+
.pack()
|
|
95
|
+
.on('data', (chunk) => chunks.push(chunk))
|
|
96
|
+
.on('end', () => {
|
|
97
|
+
resolve(Buffer.concat(chunks).toString('base64'));
|
|
98
|
+
})
|
|
99
|
+
.on('error', (err) => {
|
|
100
|
+
// eslint-disable-line promise/prefer-await-to-callbacks
|
|
101
|
+
reject(err);
|
|
102
|
+
});
|
|
95
103
|
});
|
|
96
104
|
}
|
|
97
105
|
|
|
@@ -101,11 +109,15 @@ async function imageToBase64 (image) {
|
|
|
101
109
|
* @param {PNG} image The image to mutate by cropping
|
|
102
110
|
* @param {Region} rect The selected region of image
|
|
103
111
|
*/
|
|
104
|
-
function cropImage
|
|
112
|
+
function cropImage(image, rect) {
|
|
105
113
|
const imageRect = {width: image.width, height: image.height};
|
|
106
114
|
const interRect = getRectIntersection(rect, imageRect);
|
|
107
115
|
if (interRect.width < rect.width || interRect.height < rect.height) {
|
|
108
|
-
throw new Error(
|
|
116
|
+
throw new Error(
|
|
117
|
+
`Cannot crop ${JSON.stringify(rect)} from ${JSON.stringify(
|
|
118
|
+
imageRect
|
|
119
|
+
)} because the intersection between them was not the size of the rect`
|
|
120
|
+
);
|
|
109
121
|
}
|
|
110
122
|
|
|
111
123
|
const firstVerticalPixel = interRect.top;
|
|
@@ -130,17 +142,23 @@ function cropImage (image, rect) {
|
|
|
130
142
|
return image;
|
|
131
143
|
}
|
|
132
144
|
|
|
133
|
-
function getRectIntersection
|
|
145
|
+
function getRectIntersection(rect, imageSize) {
|
|
134
146
|
const left = rect.left >= imageSize.width ? imageSize.width : rect.left;
|
|
135
147
|
const top = rect.top >= imageSize.height ? imageSize.height : rect.top;
|
|
136
|
-
const width = imageSize.width >=
|
|
137
|
-
const height = imageSize.height >=
|
|
148
|
+
const width = imageSize.width >= left + rect.width ? rect.width : imageSize.width - left;
|
|
149
|
+
const height = imageSize.height >= top + rect.height ? rect.height : imageSize.height - top;
|
|
138
150
|
return {left, top, width, height};
|
|
139
151
|
}
|
|
140
152
|
|
|
141
153
|
export {
|
|
142
|
-
cropBase64Image,
|
|
143
|
-
|
|
154
|
+
cropBase64Image,
|
|
155
|
+
base64ToImage,
|
|
156
|
+
imageToBase64,
|
|
157
|
+
cropImage,
|
|
158
|
+
getJimpImage,
|
|
159
|
+
MIME_JPEG,
|
|
160
|
+
MIME_PNG,
|
|
161
|
+
MIME_BMP,
|
|
144
162
|
};
|
|
145
163
|
|
|
146
164
|
/**
|
package/lib/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as tempDir from './tempdir';
|
|
2
2
|
import * as system from './system';
|
|
3
3
|
import * as util from './util';
|
|
4
|
-
import {
|
|
4
|
+
import {fs} from './fs';
|
|
5
5
|
import * as net from './net';
|
|
6
6
|
import * as plist from './plist';
|
|
7
|
-
import {
|
|
7
|
+
import {mkdirp} from './mkdirp';
|
|
8
8
|
import * as logger from './logging';
|
|
9
9
|
import * as process from './process';
|
|
10
10
|
import * as zip from './zip';
|
|
@@ -13,16 +13,47 @@ import * as mjpeg from './mjpeg';
|
|
|
13
13
|
import * as node from './node';
|
|
14
14
|
import * as timing from './timing';
|
|
15
15
|
import * as env from './env';
|
|
16
|
+
import * as console from './console';
|
|
16
17
|
|
|
17
|
-
export {
|
|
18
|
+
export {npm} from './npm';
|
|
18
19
|
|
|
19
|
-
const {
|
|
20
|
+
const {cancellableDelay} = util;
|
|
20
21
|
|
|
21
22
|
export {
|
|
22
|
-
tempDir,
|
|
23
|
-
|
|
23
|
+
tempDir,
|
|
24
|
+
system,
|
|
25
|
+
util,
|
|
26
|
+
fs,
|
|
27
|
+
cancellableDelay,
|
|
28
|
+
plist,
|
|
29
|
+
mkdirp,
|
|
30
|
+
logger,
|
|
31
|
+
process,
|
|
32
|
+
zip,
|
|
33
|
+
imageUtil,
|
|
34
|
+
net,
|
|
35
|
+
mjpeg,
|
|
36
|
+
node,
|
|
37
|
+
timing,
|
|
38
|
+
env,
|
|
39
|
+
console,
|
|
24
40
|
};
|
|
25
41
|
export default {
|
|
26
|
-
tempDir,
|
|
27
|
-
|
|
42
|
+
tempDir,
|
|
43
|
+
system,
|
|
44
|
+
util,
|
|
45
|
+
fs,
|
|
46
|
+
cancellableDelay,
|
|
47
|
+
plist,
|
|
48
|
+
mkdirp,
|
|
49
|
+
logger,
|
|
50
|
+
process,
|
|
51
|
+
zip,
|
|
52
|
+
imageUtil,
|
|
53
|
+
net,
|
|
54
|
+
mjpeg,
|
|
55
|
+
node,
|
|
56
|
+
timing,
|
|
57
|
+
env,
|
|
58
|
+
console,
|
|
28
59
|
};
|
package/lib/log-internal.js
CHANGED
|
@@ -3,9 +3,8 @@ import _ from 'lodash';
|
|
|
3
3
|
|
|
4
4
|
const DEFAULT_REPLACER = '**SECURE**';
|
|
5
5
|
|
|
6
|
-
|
|
7
6
|
class SecureValuesPreprocessor {
|
|
8
|
-
constructor
|
|
7
|
+
constructor() {
|
|
9
8
|
this._rules = [];
|
|
10
9
|
}
|
|
11
10
|
|
|
@@ -13,7 +12,7 @@ class SecureValuesPreprocessor {
|
|
|
13
12
|
* @returns {Array<SecureValuePreprocessingRule>} The list of successfully
|
|
14
13
|
* parsed preprocessing rules
|
|
15
14
|
*/
|
|
16
|
-
get rules
|
|
15
|
+
get rules() {
|
|
17
16
|
return this._rules;
|
|
18
17
|
}
|
|
19
18
|
|
|
@@ -25,7 +24,7 @@ class SecureValuesPreprocessor {
|
|
|
25
24
|
* @throws {Error} If there was an error while parsing the rule
|
|
26
25
|
* @returns {SecureValuePreprocessingRule} The parsed rule
|
|
27
26
|
*/
|
|
28
|
-
parseRule
|
|
27
|
+
parseRule(rule) {
|
|
29
28
|
let pattern;
|
|
30
29
|
let replacer = DEFAULT_REPLACER;
|
|
31
30
|
let flags = ['g'];
|
|
@@ -37,17 +36,23 @@ class SecureValuesPreprocessor {
|
|
|
37
36
|
} else if (_.isPlainObject(rule)) {
|
|
38
37
|
if (_.has(rule, 'pattern')) {
|
|
39
38
|
if (!_.isString(rule.pattern) || rule.pattern.length === 0) {
|
|
40
|
-
throw new Error(
|
|
39
|
+
throw new Error(
|
|
40
|
+
`${JSON.stringify(rule)} -> The value of 'pattern' must be a valid non-empty string`
|
|
41
|
+
);
|
|
41
42
|
}
|
|
42
43
|
pattern = rule.pattern;
|
|
43
44
|
} else if (_.has(rule, 'text')) {
|
|
44
45
|
if (!_.isString(rule.text) || rule.text.length === 0) {
|
|
45
|
-
throw new Error(
|
|
46
|
+
throw new Error(
|
|
47
|
+
`${JSON.stringify(rule)} -> The value of 'text' must be a valid non-empty string`
|
|
48
|
+
);
|
|
46
49
|
}
|
|
47
50
|
pattern = `\\b${_.escapeRegExp(rule.text)}\\b`;
|
|
48
51
|
}
|
|
49
52
|
if (!pattern) {
|
|
50
|
-
throw new Error(
|
|
53
|
+
throw new Error(
|
|
54
|
+
`${JSON.stringify(rule)} -> Must either have a field named 'pattern' or 'text'`
|
|
55
|
+
);
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
if (_.has(rule, 'flags')) {
|
|
@@ -83,12 +88,12 @@ class SecureValuesPreprocessor {
|
|
|
83
88
|
* @returns {Promise<string[]>} The list of issues found while parsing each rule.
|
|
84
89
|
* An empty list is returned if no rule parsing issues were found
|
|
85
90
|
*/
|
|
86
|
-
async loadRules
|
|
91
|
+
async loadRules(source) {
|
|
87
92
|
let rules;
|
|
88
93
|
if (_.isArray(source)) {
|
|
89
94
|
rules = source;
|
|
90
95
|
} else {
|
|
91
|
-
if (!await fs.exists(source)) {
|
|
96
|
+
if (!(await fs.exists(source))) {
|
|
92
97
|
throw new Error(`'${source}' does not exist or is not accessible`);
|
|
93
98
|
}
|
|
94
99
|
try {
|
|
@@ -121,7 +126,7 @@ class SecureValuesPreprocessor {
|
|
|
121
126
|
* @param {string} str The string to make replacements in
|
|
122
127
|
* @returns {string} The string with replacements made
|
|
123
128
|
*/
|
|
124
|
-
preprocess
|
|
129
|
+
preprocess(str) {
|
|
125
130
|
if (this._rules.length === 0 || !_.isString(str)) {
|
|
126
131
|
return str;
|
|
127
132
|
}
|
|
@@ -136,7 +141,7 @@ class SecureValuesPreprocessor {
|
|
|
136
141
|
|
|
137
142
|
const SECURE_VALUES_PREPROCESSOR = new SecureValuesPreprocessor();
|
|
138
143
|
|
|
139
|
-
export {
|
|
144
|
+
export {SECURE_VALUES_PREPROCESSOR, SecureValuesPreprocessor};
|
|
140
145
|
export default SECURE_VALUES_PREPROCESSOR;
|
|
141
146
|
|
|
142
147
|
/**
|
package/lib/logger.js
CHANGED
package/lib/logging.js
CHANGED
|
@@ -1,32 +1,38 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
import npmlog from 'npmlog';
|
|
2
4
|
import _ from 'lodash';
|
|
3
|
-
import {
|
|
5
|
+
import {unleakString} from './util';
|
|
4
6
|
import moment from 'moment';
|
|
5
7
|
import SECURE_VALUES_PREPROCESSOR from './log-internal';
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
+
/** @type {import('@appium/types').AppiumLoggerLevel[]} */
|
|
10
|
+
export const LEVELS = ['silly', 'verbose', 'debug', 'info', 'http', 'warn', 'error'];
|
|
9
11
|
const MAX_LOG_RECORDS_COUNT = 3000;
|
|
10
12
|
|
|
11
13
|
const PREFIX_TIMESTAMP_FORMAT = 'HH-mm-ss:SSS';
|
|
12
14
|
|
|
13
15
|
// mock log object used in testing mode
|
|
14
16
|
let mockLog = {};
|
|
15
|
-
for (let level of
|
|
17
|
+
for (let level of LEVELS) {
|
|
16
18
|
mockLog[level] = () => {};
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
/**
|
|
22
|
+
*
|
|
23
|
+
* @param {import('npmlog').Logger} logger
|
|
24
|
+
*/
|
|
25
|
+
function patchLogger(logger) {
|
|
20
26
|
if (!logger.debug) {
|
|
21
|
-
logger.addLevel('debug', 1000, {
|
|
27
|
+
logger.addLevel('debug', 1000, {fg: 'blue', bg: 'black'}, 'dbug');
|
|
22
28
|
}
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
/**
|
|
26
32
|
*
|
|
27
|
-
* @returns {[npmlog.Logger, boolean]}
|
|
33
|
+
* @returns {[import('npmlog').Logger, boolean]}
|
|
28
34
|
*/
|
|
29
|
-
function _getLogger
|
|
35
|
+
function _getLogger() {
|
|
30
36
|
// check if the user set the `_TESTING` or `_FORCE_LOGS` flag
|
|
31
37
|
const testingMode = process.env._TESTING === '1';
|
|
32
38
|
const forceLogMode = process.env._FORCE_LOGS === '1';
|
|
@@ -49,52 +55,50 @@ function _getLogger () {
|
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
/**
|
|
52
|
-
* @param {
|
|
58
|
+
* @param {AppiumLoggerPrefix?} prefix
|
|
53
59
|
* @param {boolean} logTimestamp whether to include timestamps into log prefixes
|
|
54
60
|
* @returns {string}
|
|
55
61
|
*/
|
|
56
|
-
function getActualPrefix
|
|
62
|
+
function getActualPrefix(prefix, logTimestamp = false) {
|
|
57
63
|
const result = (_.isFunction(prefix) ? prefix() : prefix) ?? '';
|
|
58
|
-
return logTimestamp
|
|
59
|
-
? `[${moment().format(PREFIX_TIMESTAMP_FORMAT)}] ${result}`
|
|
60
|
-
: result;
|
|
64
|
+
return logTimestamp ? `[${moment().format(PREFIX_TIMESTAMP_FORMAT)}] ${result}` : result;
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
/**
|
|
64
68
|
*
|
|
65
|
-
* @param {
|
|
69
|
+
* @param {AppiumLoggerPrefix?} prefix
|
|
66
70
|
* @returns {AppiumLogger}
|
|
67
71
|
*/
|
|
68
|
-
function getLogger
|
|
72
|
+
function getLogger(prefix = null) {
|
|
69
73
|
let [logger, usingGlobalLog] = _getLogger();
|
|
70
74
|
|
|
71
75
|
// wrap the logger so that we can catch and modify any logging
|
|
72
76
|
let wrappedLogger = {
|
|
73
77
|
unwrap: () => logger,
|
|
74
|
-
levels:
|
|
78
|
+
levels: LEVELS,
|
|
75
79
|
prefix,
|
|
76
80
|
};
|
|
77
81
|
|
|
78
82
|
// allow access to the level of the underlying logger
|
|
79
83
|
Object.defineProperty(wrappedLogger, 'level', {
|
|
80
|
-
get
|
|
84
|
+
get() {
|
|
81
85
|
return logger.level;
|
|
82
86
|
},
|
|
83
|
-
set
|
|
87
|
+
set(newValue) {
|
|
84
88
|
logger.level = newValue;
|
|
85
89
|
},
|
|
86
90
|
enumerable: true,
|
|
87
|
-
configurable: true
|
|
91
|
+
configurable: true,
|
|
88
92
|
});
|
|
89
93
|
|
|
90
94
|
const logTimestamp = process.env._LOG_TIMESTAMP === '1';
|
|
91
95
|
|
|
92
96
|
// add all the levels from `npmlog`, and map to the underlying logger
|
|
93
|
-
for (const level of
|
|
94
|
-
wrappedLogger[level] = function (...args) {
|
|
97
|
+
for (const level of LEVELS) {
|
|
98
|
+
wrappedLogger[level] = /** @param {...any} args */ function (...args) {
|
|
95
99
|
const actualPrefix = getActualPrefix(this.prefix, logTimestamp);
|
|
96
100
|
for (const arg of args) {
|
|
97
|
-
const out =
|
|
101
|
+
const out = _.isError(arg) && arg.stack ? arg.stack : `${arg}`;
|
|
98
102
|
for (const line of out.split('\n')) {
|
|
99
103
|
// it is necessary to unleak each line because `split` call
|
|
100
104
|
// creates "views" to the original string as well as the `substring` one
|
|
@@ -108,7 +112,7 @@ function getLogger (prefix = null) {
|
|
|
108
112
|
wrappedLogger.errorAndThrow = function (err) {
|
|
109
113
|
this.error(err);
|
|
110
114
|
// make sure we have an `Error` object. Wrap if necessary
|
|
111
|
-
throw
|
|
115
|
+
throw _.isError(err) ? err : new Error(unleakString(err));
|
|
112
116
|
};
|
|
113
117
|
if (!usingGlobalLog) {
|
|
114
118
|
// if we're not using a global log specified from some top-level package,
|
|
@@ -116,7 +120,7 @@ function getLogger (prefix = null) {
|
|
|
116
120
|
// package set the log level
|
|
117
121
|
wrappedLogger.level = 'verbose';
|
|
118
122
|
}
|
|
119
|
-
return /** @type {AppiumLogger} */(wrappedLogger);
|
|
123
|
+
return /** @type {AppiumLogger} */ (wrappedLogger);
|
|
120
124
|
}
|
|
121
125
|
|
|
122
126
|
/**
|
|
@@ -140,7 +144,7 @@ function getLogger (prefix = null) {
|
|
|
140
144
|
* @throws {Error} If the given file cannot be loaded
|
|
141
145
|
* @returns {Promise<LoadResult>}
|
|
142
146
|
*/
|
|
143
|
-
async function loadSecureValuesPreprocessingRules
|
|
147
|
+
async function loadSecureValuesPreprocessingRules(rulesJsonPath) {
|
|
144
148
|
const issues = await SECURE_VALUES_PREPROCESSOR.loadRules(rulesJsonPath);
|
|
145
149
|
return {
|
|
146
150
|
issues,
|
|
@@ -151,13 +155,11 @@ async function loadSecureValuesPreprocessingRules (rulesJsonPath) {
|
|
|
151
155
|
// export a default logger with no prefix
|
|
152
156
|
const log = getLogger();
|
|
153
157
|
|
|
154
|
-
export {
|
|
158
|
+
export {log, patchLogger, getLogger, loadSecureValuesPreprocessingRules};
|
|
155
159
|
export default log;
|
|
156
160
|
|
|
157
161
|
/**
|
|
158
|
-
* @typedef {import('@appium/types').
|
|
159
|
-
*/
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
+
* @typedef {import('@appium/types').AppiumLoggerPrefix} AppiumLoggerPrefix
|
|
162
163
|
* @typedef {import('@appium/types').AppiumLogger} AppiumLogger
|
|
164
|
+
* @typedef {import('@appium/types').AppiumLoggerLevel} AppiumLoggerLevel
|
|
163
165
|
*/
|
package/lib/mjpeg.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import log from './logger';
|
|
3
3
|
import B from 'bluebird';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import {getJimpImage, MIME_PNG} from './image-util';
|
|
5
|
+
import {Writable} from 'stream';
|
|
6
|
+
import {requirePackage} from './node';
|
|
7
7
|
import axios from 'axios';
|
|
8
8
|
|
|
9
9
|
// lazy load this, as it might not be available
|
|
@@ -12,15 +12,17 @@ let MJpegConsumer = null;
|
|
|
12
12
|
/**
|
|
13
13
|
* @throws {Error} If `mjpeg-consumer` module is not installed or cannot be loaded
|
|
14
14
|
*/
|
|
15
|
-
async function initMJpegConsumer
|
|
15
|
+
async function initMJpegConsumer() {
|
|
16
16
|
if (!MJpegConsumer) {
|
|
17
17
|
try {
|
|
18
18
|
MJpegConsumer = await requirePackage('mjpeg-consumer');
|
|
19
19
|
} catch (ign) {}
|
|
20
20
|
}
|
|
21
21
|
if (!MJpegConsumer) {
|
|
22
|
-
throw new Error(
|
|
23
|
-
|
|
22
|
+
throw new Error(
|
|
23
|
+
'mjpeg-consumer module is required to use MJPEG-over-HTTP features. ' +
|
|
24
|
+
'Please install it first (npm i -g mjpeg-consumer) and restart Appium.'
|
|
25
|
+
);
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
|
|
@@ -29,7 +31,6 @@ const MJPEG_SERVER_TIMEOUT_MS = 10000;
|
|
|
29
31
|
|
|
30
32
|
/** Class which stores the last bit of data streamed into it */
|
|
31
33
|
class MJpegStream extends Writable {
|
|
32
|
-
|
|
33
34
|
/**
|
|
34
35
|
* @type {number}
|
|
35
36
|
*/
|
|
@@ -42,7 +43,7 @@ class MJpegStream extends Writable {
|
|
|
42
43
|
* called in the case of any errors.
|
|
43
44
|
* @param {object} [options={}] - Options to pass to the Writable constructor
|
|
44
45
|
*/
|
|
45
|
-
constructor
|
|
46
|
+
constructor(mJpegUrl, errorHandler = _.noop, options = {}) {
|
|
46
47
|
super(options);
|
|
47
48
|
|
|
48
49
|
this.errorHandler = errorHandler;
|
|
@@ -56,8 +57,8 @@ class MJpegStream extends Writable {
|
|
|
56
57
|
* @returns {?string} base64-encoded JPEG image data
|
|
57
58
|
* or `null` if no image can be parsed
|
|
58
59
|
*/
|
|
59
|
-
get lastChunkBase64
|
|
60
|
-
const lastChunk = /** @type {Buffer} */(this.lastChunk);
|
|
60
|
+
get lastChunkBase64() {
|
|
61
|
+
const lastChunk = /** @type {Buffer} */ (this.lastChunk);
|
|
61
62
|
return !_.isEmpty(this.lastChunk) && _.isBuffer(this.lastChunk)
|
|
62
63
|
? lastChunk.toString('base64')
|
|
63
64
|
: null;
|
|
@@ -69,8 +70,8 @@ class MJpegStream extends Writable {
|
|
|
69
70
|
* @returns {Promise<Buffer?>} PNG image data or `null` if no PNG
|
|
70
71
|
* image can be parsed
|
|
71
72
|
*/
|
|
72
|
-
async lastChunkPNG
|
|
73
|
-
const lastChunk = /** @type {Buffer} */(this.lastChunk);
|
|
73
|
+
async lastChunkPNG() {
|
|
74
|
+
const lastChunk = /** @type {Buffer} */ (this.lastChunk);
|
|
74
75
|
if (_.isEmpty(lastChunk) || !_.isBuffer(lastChunk)) {
|
|
75
76
|
return null;
|
|
76
77
|
}
|
|
@@ -89,7 +90,7 @@ class MJpegStream extends Writable {
|
|
|
89
90
|
* @returns {Promise<string?>} base64-encoded PNG image data
|
|
90
91
|
* or `null` if no image can be parsed
|
|
91
92
|
*/
|
|
92
|
-
async lastChunkPNGBase64
|
|
93
|
+
async lastChunkPNGBase64() {
|
|
93
94
|
const png = await this.lastChunkPNG();
|
|
94
95
|
return png ? png.toString('base64') : null;
|
|
95
96
|
}
|
|
@@ -97,7 +98,7 @@ class MJpegStream extends Writable {
|
|
|
97
98
|
/**
|
|
98
99
|
* Reset internal state
|
|
99
100
|
*/
|
|
100
|
-
clear
|
|
101
|
+
clear() {
|
|
101
102
|
this.registerStartSuccess = null;
|
|
102
103
|
this.registerStartFailure = null;
|
|
103
104
|
this.responseStream = null;
|
|
@@ -109,7 +110,7 @@ class MJpegStream extends Writable {
|
|
|
109
110
|
/**
|
|
110
111
|
* Start reading the MJpeg stream and storing the last image
|
|
111
112
|
*/
|
|
112
|
-
async start
|
|
113
|
+
async start(serverTimeout = MJPEG_SERVER_TIMEOUT_MS) {
|
|
113
114
|
// ensure we're not started already
|
|
114
115
|
this.stop();
|
|
115
116
|
|
|
@@ -123,10 +124,12 @@ class MJpegStream extends Writable {
|
|
|
123
124
|
this.registerStartSuccess = res;
|
|
124
125
|
this.registerStartFailure = rej;
|
|
125
126
|
})
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
.timeout(
|
|
129
|
-
|
|
127
|
+
// start a timeout so that if the server does not return data, we don't
|
|
128
|
+
// block forever.
|
|
129
|
+
.timeout(
|
|
130
|
+
serverTimeout,
|
|
131
|
+
`Waited ${serverTimeout}ms but the MJPEG server never sent any images`
|
|
132
|
+
);
|
|
130
133
|
|
|
131
134
|
const url = this.url;
|
|
132
135
|
const onErr = (err) => {
|
|
@@ -145,11 +148,13 @@ class MJpegStream extends Writable {
|
|
|
145
148
|
};
|
|
146
149
|
|
|
147
150
|
try {
|
|
148
|
-
this.responseStream = (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
151
|
+
this.responseStream = (
|
|
152
|
+
await axios({
|
|
153
|
+
url,
|
|
154
|
+
responseType: 'stream',
|
|
155
|
+
timeout: serverTimeout,
|
|
156
|
+
})
|
|
157
|
+
).data;
|
|
153
158
|
} catch (e) {
|
|
154
159
|
return onErr(e);
|
|
155
160
|
}
|
|
@@ -167,7 +172,7 @@ class MJpegStream extends Writable {
|
|
|
167
172
|
* Stop reading the MJpeg stream. Ensure we disconnect all the pipes and stop
|
|
168
173
|
* the HTTP request itself. Then reset the state.
|
|
169
174
|
*/
|
|
170
|
-
stop
|
|
175
|
+
stop() {
|
|
171
176
|
if (!this.consumer) {
|
|
172
177
|
return;
|
|
173
178
|
}
|
|
@@ -184,7 +189,7 @@ class MJpegStream extends Writable {
|
|
|
184
189
|
* @override
|
|
185
190
|
* @param {Buffer} data - binary data streamed from the MJpeg consumer
|
|
186
191
|
*/
|
|
187
|
-
write
|
|
192
|
+
write(data) {
|
|
188
193
|
this.lastChunk = data;
|
|
189
194
|
this.updateCount++;
|
|
190
195
|
|
|
@@ -197,4 +202,4 @@ class MJpegStream extends Writable {
|
|
|
197
202
|
}
|
|
198
203
|
}
|
|
199
204
|
|
|
200
|
-
export {
|
|
205
|
+
export {MJpegStream};
|
package/lib/mkdirp.js
CHANGED