@appium/support 7.0.4 → 7.0.6
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 +42 -88
- package/build/lib/console.d.ts.map +1 -1
- package/build/lib/console.js +25 -85
- package/build/lib/console.js.map +1 -1
- package/build/lib/doctor.d.ts +6 -18
- package/build/lib/doctor.d.ts.map +1 -1
- package/build/lib/doctor.js +0 -15
- package/build/lib/doctor.js.map +1 -1
- package/build/lib/env.d.ts +14 -20
- package/build/lib/env.d.ts.map +1 -1
- package/build/lib/env.js +24 -61
- package/build/lib/env.js.map +1 -1
- package/build/lib/fs.d.ts +109 -148
- package/build/lib/fs.d.ts.map +1 -1
- package/build/lib/fs.js +130 -230
- package/build/lib/fs.js.map +1 -1
- package/build/lib/image-util.d.ts +7 -6
- package/build/lib/image-util.d.ts.map +1 -1
- package/build/lib/image-util.js +9 -6
- package/build/lib/image-util.js.map +1 -1
- package/build/lib/index.d.ts +19 -17
- package/build/lib/index.d.ts.map +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/logger.js.map +1 -1
- package/build/lib/logging.d.ts +7 -15
- package/build/lib/logging.d.ts.map +1 -1
- package/build/lib/logging.js +36 -62
- package/build/lib/logging.js.map +1 -1
- package/build/lib/mjpeg.d.ts +19 -56
- package/build/lib/mjpeg.d.ts.map +1 -1
- package/build/lib/mjpeg.js +55 -78
- package/build/lib/mjpeg.js.map +1 -1
- package/build/lib/mkdirp.d.ts +4 -1
- package/build/lib/mkdirp.d.ts.map +1 -1
- package/build/lib/mkdirp.js +1 -2
- package/build/lib/mkdirp.js.map +1 -1
- package/build/lib/net.d.ts +52 -90
- package/build/lib/net.d.ts.map +1 -1
- package/build/lib/net.js +104 -193
- package/build/lib/net.js.map +1 -1
- package/build/lib/node.d.ts +16 -17
- package/build/lib/node.d.ts.map +1 -1
- package/build/lib/node.js +115 -120
- package/build/lib/node.js.map +1 -1
- package/build/lib/npm.d.ts +65 -86
- package/build/lib/npm.d.ts.map +1 -1
- package/build/lib/npm.js +64 -122
- package/build/lib/npm.js.map +1 -1
- package/build/lib/plist.d.ts +36 -29
- package/build/lib/plist.d.ts.map +1 -1
- package/build/lib/plist.js +62 -59
- package/build/lib/plist.js.map +1 -1
- package/build/lib/process.d.ts +19 -2
- package/build/lib/process.d.ts.map +1 -1
- package/build/lib/process.js +24 -7
- package/build/lib/process.js.map +1 -1
- package/build/lib/system.d.ts +41 -6
- package/build/lib/system.d.ts.map +1 -1
- package/build/lib/system.js +49 -14
- package/build/lib/system.js.map +1 -1
- package/build/lib/tempdir.d.ts +26 -49
- package/build/lib/tempdir.d.ts.map +1 -1
- package/build/lib/tempdir.js +46 -78
- package/build/lib/tempdir.js.map +1 -1
- package/build/lib/timing.d.ts +28 -22
- package/build/lib/timing.d.ts.map +1 -1
- package/build/lib/timing.js +16 -17
- package/build/lib/timing.js.map +1 -1
- package/build/lib/util.d.ts +164 -181
- package/build/lib/util.d.ts.map +1 -1
- package/build/lib/util.js +198 -253
- package/build/lib/util.js.map +1 -1
- package/build/lib/zip.d.ts +81 -139
- package/build/lib/zip.d.ts.map +1 -1
- package/build/lib/zip.js +235 -283
- package/build/lib/zip.js.map +1 -1
- package/lib/console.ts +139 -0
- package/lib/{doctor.js → doctor.ts} +6 -20
- package/lib/{env.js → env.ts} +34 -62
- package/lib/fs.ts +453 -0
- package/lib/image-util.ts +40 -0
- package/lib/index.ts +1 -0
- package/lib/{logger.js → logger.ts} +1 -1
- package/lib/logging.ts +157 -0
- package/lib/mjpeg.ts +186 -0
- package/lib/{mkdirp.js → mkdirp.ts} +2 -2
- package/lib/net.ts +305 -0
- package/lib/{node.js → node.ts} +136 -135
- package/lib/npm.ts +291 -0
- package/lib/plist.ts +187 -0
- package/lib/process.ts +62 -0
- package/lib/system.ts +95 -0
- package/lib/tempdir.ts +115 -0
- package/lib/{timing.js → timing.ts} +28 -33
- package/lib/util.ts +561 -0
- package/lib/{zip.js → zip.ts} +344 -299
- package/package.json +24 -26
- package/tsconfig.json +3 -5
- package/index.js +0 -1
- package/lib/console.js +0 -173
- package/lib/fs.js +0 -496
- package/lib/image-util.js +0 -32
- package/lib/logging.js +0 -145
- package/lib/mjpeg.js +0 -207
- package/lib/net.js +0 -336
- package/lib/npm.js +0 -310
- package/lib/plist.js +0 -182
- package/lib/process.js +0 -46
- package/lib/system.js +0 -48
- package/lib/tempdir.js +0 -131
- package/lib/util.js +0 -585
package/lib/npm.js
DELETED
|
@@ -1,310 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import * as semver from 'semver';
|
|
5
|
-
import {hasAppiumDependency} from './env';
|
|
6
|
-
import {exec} from 'teen_process';
|
|
7
|
-
import {fs} from './fs';
|
|
8
|
-
import * as util from './util';
|
|
9
|
-
import * as system from './system';
|
|
10
|
-
import resolveFrom from 'resolve-from';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Relative path to directory containing any Appium internal files
|
|
14
|
-
* XXX: this is duplicated in `appium/lib/constants.js`.
|
|
15
|
-
*/
|
|
16
|
-
export const CACHE_DIR_RELATIVE_PATH = path.join('node_modules', '.cache', 'appium');
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Relative path to lockfile used when installing an extension via `appium`
|
|
20
|
-
*/
|
|
21
|
-
export const INSTALL_LOCKFILE_RELATIVE_PATH = path.join(CACHE_DIR_RELATIVE_PATH, '.install.lock');
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* XXX: This should probably be a singleton, but it isn't. Maybe this module should just export functions?
|
|
25
|
-
*/
|
|
26
|
-
export class NPM {
|
|
27
|
-
/**
|
|
28
|
-
* Returns path to "install" lockfile
|
|
29
|
-
* @private
|
|
30
|
-
* @param {string} cwd
|
|
31
|
-
*/
|
|
32
|
-
_getInstallLockfilePath(cwd) {
|
|
33
|
-
return path.join(cwd, INSTALL_LOCKFILE_RELATIVE_PATH);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Execute `npm` with given args.
|
|
38
|
-
*
|
|
39
|
-
* If the process exits with a nonzero code, the contents of `STDOUT` and `STDERR` will be in the
|
|
40
|
-
* `message` of any rejected error.
|
|
41
|
-
* @param {string} cmd
|
|
42
|
-
* @param {string[]} args
|
|
43
|
-
* @param {ExecOpts} opts
|
|
44
|
-
* @param {Omit<TeenProcessExecOptions, 'cwd'>} [execOpts]
|
|
45
|
-
*/
|
|
46
|
-
async exec(cmd, args, opts, execOpts = {}) {
|
|
47
|
-
const {cwd, json, lockFile} = opts;
|
|
48
|
-
|
|
49
|
-
// make sure we perform the current operation in cwd
|
|
50
|
-
/** @type {TeenProcessExecOptions} */
|
|
51
|
-
const teenProcessExecOpts = {
|
|
52
|
-
...execOpts,
|
|
53
|
-
// https://github.com/nodejs/node/issues/52572
|
|
54
|
-
shell: system.isWindows() || execOpts.shell,
|
|
55
|
-
cwd,
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
args.unshift(cmd);
|
|
59
|
-
if (json) {
|
|
60
|
-
args.push('--json');
|
|
61
|
-
}
|
|
62
|
-
const npmCmd = system.isWindows() ? 'npm.cmd' : 'npm';
|
|
63
|
-
let runner = async () => await exec(npmCmd, args, teenProcessExecOpts);
|
|
64
|
-
if (lockFile) {
|
|
65
|
-
const acquireLock = util.getLockFileGuard(lockFile);
|
|
66
|
-
const _runner = runner;
|
|
67
|
-
runner = async () => await acquireLock(_runner);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/** @type {import('teen_process').TeenProcessExecResult<string> & {json?: any}} */
|
|
71
|
-
let ret;
|
|
72
|
-
try {
|
|
73
|
-
const {stdout, stderr, code} = await runner();
|
|
74
|
-
ret = {stdout, stderr, code};
|
|
75
|
-
// if possible, parse NPM's json output. During NPM install 3rd-party
|
|
76
|
-
// packages can write to stdout, so sometimes the json output can't be
|
|
77
|
-
// guaranteed to be parseable
|
|
78
|
-
try {
|
|
79
|
-
ret.json = JSON.parse(stdout);
|
|
80
|
-
} catch {}
|
|
81
|
-
} catch (e) {
|
|
82
|
-
const {
|
|
83
|
-
stdout = '',
|
|
84
|
-
stderr = '',
|
|
85
|
-
code = null,
|
|
86
|
-
} = /** @type {import('teen_process').ExecError} */ (e);
|
|
87
|
-
const err = new Error(
|
|
88
|
-
`npm command '${args.join(
|
|
89
|
-
' '
|
|
90
|
-
)}' failed with code ${code}.\n\nSTDOUT:\n${stdout.trim()}\n\nSTDERR:\n${stderr.trim()}`
|
|
91
|
-
);
|
|
92
|
-
throw err;
|
|
93
|
-
}
|
|
94
|
-
return ret;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* @param {string} cwd
|
|
99
|
-
* @param {string} pkg
|
|
100
|
-
* @returns {Promise<string?>}
|
|
101
|
-
*/
|
|
102
|
-
async getLatestVersion(cwd, pkg) {
|
|
103
|
-
try {
|
|
104
|
-
return (
|
|
105
|
-
(
|
|
106
|
-
await this.exec('view', [pkg, 'dist-tags'], {
|
|
107
|
-
json: true,
|
|
108
|
-
cwd,
|
|
109
|
-
})
|
|
110
|
-
).json?.latest ?? null
|
|
111
|
-
);
|
|
112
|
-
} catch (err) {
|
|
113
|
-
if (!err?.message.includes('E404')) {
|
|
114
|
-
throw err;
|
|
115
|
-
}
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* @param {string} cwd
|
|
122
|
-
* @param {string} pkg
|
|
123
|
-
* @param {string} curVersion
|
|
124
|
-
* @returns {Promise<string?>}
|
|
125
|
-
*/
|
|
126
|
-
async getLatestSafeUpgradeVersion(cwd, pkg, curVersion) {
|
|
127
|
-
try {
|
|
128
|
-
const allVersions = (
|
|
129
|
-
await this.exec('view', [pkg, 'versions'], {
|
|
130
|
-
json: true,
|
|
131
|
-
cwd,
|
|
132
|
-
})
|
|
133
|
-
).json;
|
|
134
|
-
return this.getLatestSafeUpgradeFromVersions(curVersion, allVersions);
|
|
135
|
-
} catch (err) {
|
|
136
|
-
if (!err?.message.includes('E404')) {
|
|
137
|
-
throw err;
|
|
138
|
-
}
|
|
139
|
-
return null;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Runs `npm ls`, optionally for a particular package.
|
|
145
|
-
* @param {string} cwd
|
|
146
|
-
* @param {string} [pkg]
|
|
147
|
-
*/
|
|
148
|
-
async list(cwd, pkg) {
|
|
149
|
-
return (await this.exec('list', pkg ? [pkg] : [], {cwd, json: true})).json;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Given a current version and a list of all versions for a package, return the version which is
|
|
154
|
-
* the highest safely-upgradable version (meaning not crossing any major revision boundaries, and
|
|
155
|
-
* not including any alpha/beta/rc versions)
|
|
156
|
-
*
|
|
157
|
-
* @param {string} curVersion - the current version of a package
|
|
158
|
-
* @param {Array<string>} allVersions - a list of version strings
|
|
159
|
-
*
|
|
160
|
-
* @return {string|null} - the highest safely-upgradable version, or null if there isn't one
|
|
161
|
-
*/
|
|
162
|
-
getLatestSafeUpgradeFromVersions(curVersion, allVersions) {
|
|
163
|
-
let safeUpgradeVer = null;
|
|
164
|
-
const curSemver = semver.parse(curVersion) ?? semver.parse(semver.coerce(curVersion));
|
|
165
|
-
if (curSemver === null) {
|
|
166
|
-
throw new Error(`Could not parse current version '${curVersion}'`);
|
|
167
|
-
}
|
|
168
|
-
for (const testVer of allVersions) {
|
|
169
|
-
const testSemver = semver.parse(testVer) ?? semver.parse(semver.coerce(testVer));
|
|
170
|
-
if (testSemver === null) {
|
|
171
|
-
continue;
|
|
172
|
-
}
|
|
173
|
-
// if the test version is a prerelease, ignore it
|
|
174
|
-
if (testSemver.prerelease.length > 0) {
|
|
175
|
-
continue;
|
|
176
|
-
}
|
|
177
|
-
// if the current version is later than the test version, skip this test version
|
|
178
|
-
if (curSemver.compare(testSemver) === 1) {
|
|
179
|
-
continue;
|
|
180
|
-
}
|
|
181
|
-
// if the test version is newer, but crosses a major revision boundary, also skip it
|
|
182
|
-
if (testSemver.major > curSemver.major) {
|
|
183
|
-
continue;
|
|
184
|
-
}
|
|
185
|
-
// otherwise this version is safe to upgrade to. But there might be multiple ones of this
|
|
186
|
-
// kind, so keep iterating and keeping the highest
|
|
187
|
-
if (safeUpgradeVer === null || testSemver.compare(safeUpgradeVer) === 1) {
|
|
188
|
-
safeUpgradeVer = testSemver;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
if (safeUpgradeVer) {
|
|
192
|
-
safeUpgradeVer = safeUpgradeVer.format();
|
|
193
|
-
}
|
|
194
|
-
return safeUpgradeVer;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Installs a package w/ `npm`
|
|
199
|
-
* @param {string} cwd
|
|
200
|
-
* @param {string} installStr - as in "npm install <installStr>"
|
|
201
|
-
* @param {InstallPackageOpts} opts
|
|
202
|
-
* @returns {Promise<NpmInstallReceipt>}
|
|
203
|
-
*/
|
|
204
|
-
async installPackage(cwd, installStr, {pkgName, installType}) {
|
|
205
|
-
/** @type {any} */
|
|
206
|
-
let dummyPkgJson;
|
|
207
|
-
const dummyPkgPath = path.join(cwd, 'package.json');
|
|
208
|
-
try {
|
|
209
|
-
dummyPkgJson = JSON.parse(await fs.readFile(dummyPkgPath, 'utf8'));
|
|
210
|
-
} catch (err) {
|
|
211
|
-
if (err.code === 'ENOENT') {
|
|
212
|
-
dummyPkgJson = {};
|
|
213
|
-
await fs.writeFile(dummyPkgPath, JSON.stringify(dummyPkgJson, null, 2), 'utf8');
|
|
214
|
-
} else {
|
|
215
|
-
throw err;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const installOpts = ['--save-dev', '--no-progress', '--no-audit'];
|
|
220
|
-
if (!(await hasAppiumDependency(cwd))) {
|
|
221
|
-
if (process.env.APPIUM_OMIT_PEER_DEPS) {
|
|
222
|
-
installOpts.push('--omit=peer');
|
|
223
|
-
}
|
|
224
|
-
installOpts.push('--save-exact', '--global-style', '--no-package-lock');
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
const cmd = installType === 'local' ? 'link' : 'install';
|
|
228
|
-
const res = await this.exec(cmd, [...installOpts, installStr], {
|
|
229
|
-
cwd,
|
|
230
|
-
json: true,
|
|
231
|
-
lockFile: this._getInstallLockfilePath(cwd),
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
if (res.json) {
|
|
235
|
-
// we parsed a valid json response, so if we got an error here, return that
|
|
236
|
-
// message straightaway
|
|
237
|
-
if (res.json.error) {
|
|
238
|
-
throw new Error(res.json.error);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Now read package data from the installed package to return, and make sure
|
|
243
|
-
// everything got installed ok. Remember, pkgName might end up with a / in it due to an npm
|
|
244
|
-
// org, so if so, that will get correctly exploded into multiple directories, by path.resolve here
|
|
245
|
-
// (even on Windows!)
|
|
246
|
-
const pkgJsonPath = resolveFrom(cwd, `${pkgName}/package.json`);
|
|
247
|
-
try {
|
|
248
|
-
const pkgJson = await fs.readFile(pkgJsonPath, 'utf8');
|
|
249
|
-
const pkg = JSON.parse(pkgJson);
|
|
250
|
-
return {installPath: path.dirname(pkgJsonPath), pkg};
|
|
251
|
-
} catch {
|
|
252
|
-
throw new Error(
|
|
253
|
-
'The package was not downloaded correctly; its package.json ' +
|
|
254
|
-
'did not exist or was unreadable. We looked for it at ' +
|
|
255
|
-
pkgJsonPath
|
|
256
|
-
);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* @param {string} cwd
|
|
262
|
-
* @param {string} pkg
|
|
263
|
-
*/
|
|
264
|
-
async uninstallPackage(cwd, pkg) {
|
|
265
|
-
await this.exec('uninstall', [pkg], {
|
|
266
|
-
cwd,
|
|
267
|
-
lockFile: this._getInstallLockfilePath(cwd),
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* @param {string} pkg Npm package spec to query
|
|
273
|
-
* @param {string[]} [entries=[]] Field names to be included into the
|
|
274
|
-
* resulting output. By default all fields are included.
|
|
275
|
-
* @returns {Promise<import('@appium/types').StringRecord>}
|
|
276
|
-
*/
|
|
277
|
-
async getPackageInfo(pkg, entries = []) {
|
|
278
|
-
return (await this.exec('info', [pkg, ...entries], {
|
|
279
|
-
cwd: process.cwd(),
|
|
280
|
-
json: true,
|
|
281
|
-
})).json;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
export const npm = new NPM();
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
* Options for {@link NPM.installPackage}
|
|
289
|
-
* @typedef InstallPackageOpts
|
|
290
|
-
* @property {string} pkgName - the name of the package to install
|
|
291
|
-
* @property {import('type-fest').LiteralUnion<'local', string>} [installType] - whether to install from a local path or from npm
|
|
292
|
-
*/
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Options for {@link NPM.exec}
|
|
296
|
-
* @typedef ExecOpts
|
|
297
|
-
* @property {string} cwd - Current working directory
|
|
298
|
-
* @property {boolean} [json] - If `true`, supply `--json` flag to npm and resolve w/ parsed JSON
|
|
299
|
-
* @property {string} [lockFile] - Path to lockfile to use
|
|
300
|
-
*/
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* @typedef {import('teen_process').TeenProcessExecOptions} TeenProcessExecOptions
|
|
304
|
-
*/
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* @typedef NpmInstallReceipt
|
|
308
|
-
* @property {string} installPath - Path to installed package
|
|
309
|
-
* @property {import('type-fest').PackageJson} pkg - Package data
|
|
310
|
-
*/
|
package/lib/plist.js
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
import xmlplist from 'plist';
|
|
2
|
-
import bplistCreate from 'bplist-creator';
|
|
3
|
-
import { parseFile, parseBuffer } from 'bplist-parser';
|
|
4
|
-
import {fs} from './fs';
|
|
5
|
-
import log from './logger';
|
|
6
|
-
import _ from 'lodash';
|
|
7
|
-
|
|
8
|
-
const BPLIST_IDENTIFIER = {
|
|
9
|
-
BUFFER: Buffer.from('bplist00'),
|
|
10
|
-
TEXT: 'bplist00',
|
|
11
|
-
};
|
|
12
|
-
const PLIST_IDENTIFIER = {
|
|
13
|
-
BUFFER: Buffer.from('<'),
|
|
14
|
-
TEXT: '<',
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
// XML Plist library helper
|
|
18
|
-
async function parseXmlPlistFile(plistFilename) {
|
|
19
|
-
let xmlContent = await fs.readFile(plistFilename, 'utf8');
|
|
20
|
-
return xmlplist.parse(xmlContent);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Parses a file in xml or binary format of plist
|
|
25
|
-
* @param {string} plist The plist file path
|
|
26
|
-
* @param {boolean} mustExist If set to false, this method will return an empty object when the file doesn't exist
|
|
27
|
-
* @param {boolean} quiet If set to false, the plist path will be logged in debug level
|
|
28
|
-
* @returns {Promise<any>} parsed plist JS Object
|
|
29
|
-
*/
|
|
30
|
-
async function parsePlistFile(plist, mustExist = true, quiet = true) {
|
|
31
|
-
// handle nonexistent file
|
|
32
|
-
if (!(await fs.exists(plist))) {
|
|
33
|
-
if (mustExist) {
|
|
34
|
-
throw log.errorWithException(`Plist file doesn't exist: '${plist}'`);
|
|
35
|
-
} else {
|
|
36
|
-
log.debug(`Plist file '${plist}' does not exist. Returning an empty plist.`);
|
|
37
|
-
return {};
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
let obj = {};
|
|
42
|
-
let type = 'binary';
|
|
43
|
-
try {
|
|
44
|
-
obj = await parseFile(plist);
|
|
45
|
-
if (obj.length) {
|
|
46
|
-
obj = obj[0];
|
|
47
|
-
} else {
|
|
48
|
-
throw new Error(`Binary file '${plist}'' appears to be empty`);
|
|
49
|
-
}
|
|
50
|
-
} catch {
|
|
51
|
-
try {
|
|
52
|
-
obj = await parseXmlPlistFile(plist);
|
|
53
|
-
type = 'xml';
|
|
54
|
-
} catch (err) {
|
|
55
|
-
throw log.errorWithException(`Could not parse plist file '${plist}' as XML: ${err.message}`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (!quiet) {
|
|
60
|
-
log.debug(`Parsed plist file '${plist}' as ${type}`);
|
|
61
|
-
}
|
|
62
|
-
return obj;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Updates a plist file with the given fields
|
|
67
|
-
* @param {string} plist The plist file path
|
|
68
|
-
* @param {Object} updatedFields The updated fields-value pairs
|
|
69
|
-
* @param {boolean} binary If set to false, the file will be created as a xml plist
|
|
70
|
-
* @param {boolean} mustExist If set to false, this method will update an empty plist
|
|
71
|
-
* @param {boolean} quiet If set to false, the plist path will be logged in debug level
|
|
72
|
-
*/
|
|
73
|
-
async function updatePlistFile(
|
|
74
|
-
plist,
|
|
75
|
-
updatedFields,
|
|
76
|
-
binary = true,
|
|
77
|
-
mustExist = true,
|
|
78
|
-
quiet = true
|
|
79
|
-
) {
|
|
80
|
-
let obj;
|
|
81
|
-
try {
|
|
82
|
-
obj = await parsePlistFile(plist, mustExist);
|
|
83
|
-
} catch (err) {
|
|
84
|
-
throw log.errorWithException(`Could not update plist: ${err.message}`);
|
|
85
|
-
}
|
|
86
|
-
_.extend(obj, updatedFields);
|
|
87
|
-
let newPlist = binary ? bplistCreate(obj) : xmlplist.build(obj);
|
|
88
|
-
try {
|
|
89
|
-
await fs.writeFile(plist, newPlist);
|
|
90
|
-
} catch (err) {
|
|
91
|
-
throw log.errorWithException(`Could not save plist: ${err.message}`);
|
|
92
|
-
}
|
|
93
|
-
if (!quiet) {
|
|
94
|
-
log.debug(`Wrote plist file '${plist}'`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Creates a binary plist Buffer from an object
|
|
99
|
-
* @param {Object} data The object to be turned into a binary plist
|
|
100
|
-
* @returns {Buffer} plist in the form of a binary buffer
|
|
101
|
-
*/
|
|
102
|
-
function createBinaryPlist(data) {
|
|
103
|
-
return bplistCreate(data);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Parses a Buffer into an Object
|
|
108
|
-
* @param {Buffer} data The buffer of a binary plist
|
|
109
|
-
*/
|
|
110
|
-
function parseBinaryPlist(data) {
|
|
111
|
-
return parseBuffer(data);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function getXmlPlist(data) {
|
|
115
|
-
if (_.isString(data) && data.startsWith(PLIST_IDENTIFIER.TEXT)) {
|
|
116
|
-
return data;
|
|
117
|
-
}
|
|
118
|
-
if (
|
|
119
|
-
_.isBuffer(data) &&
|
|
120
|
-
PLIST_IDENTIFIER.BUFFER.compare(data, 0, PLIST_IDENTIFIER.BUFFER.length) === 0
|
|
121
|
-
) {
|
|
122
|
-
return data.toString();
|
|
123
|
-
}
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function getBinaryPlist(data) {
|
|
128
|
-
if (_.isString(data) && data.startsWith(BPLIST_IDENTIFIER.TEXT)) {
|
|
129
|
-
return Buffer.from(data);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (
|
|
133
|
-
_.isBuffer(data) &&
|
|
134
|
-
BPLIST_IDENTIFIER.BUFFER.compare(data, 0, BPLIST_IDENTIFIER.BUFFER.length) === 0
|
|
135
|
-
) {
|
|
136
|
-
return data;
|
|
137
|
-
}
|
|
138
|
-
return null;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Creates a plist from an object
|
|
143
|
-
* @param {Object} object The JS object to be turned into a plist
|
|
144
|
-
* @param {boolean} binary Set it to true for a binary plist
|
|
145
|
-
* @returns {string|Buffer} returns a buffer or a string in respect to the binary parameter
|
|
146
|
-
*/
|
|
147
|
-
function createPlist(object, binary = false) {
|
|
148
|
-
if (binary) {
|
|
149
|
-
return createBinaryPlist(object);
|
|
150
|
-
} else {
|
|
151
|
-
return xmlplist.build(object);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Parses an buffer or a string to a JS object a plist from an object
|
|
157
|
-
* @param {string|Buffer} data The plist in the form of string or Buffer
|
|
158
|
-
* @returns {Object} parsed plist JS Object
|
|
159
|
-
* @throws Will throw an error if the plist type is unknown
|
|
160
|
-
*/
|
|
161
|
-
function parsePlist(data) {
|
|
162
|
-
let textPlist = getXmlPlist(data);
|
|
163
|
-
if (textPlist) {
|
|
164
|
-
return xmlplist.parse(textPlist);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
let binaryPlist = getBinaryPlist(data);
|
|
168
|
-
if (binaryPlist) {
|
|
169
|
-
return parseBinaryPlist(binaryPlist)[0];
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
throw new Error(`Unknown type of plist, data: ${data.toString()}`);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
export {
|
|
176
|
-
parsePlistFile,
|
|
177
|
-
parsePlist,
|
|
178
|
-
createPlist,
|
|
179
|
-
updatePlistFile,
|
|
180
|
-
createBinaryPlist,
|
|
181
|
-
parseBinaryPlist,
|
|
182
|
-
};
|
package/lib/process.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import {exec} from 'teen_process';
|
|
2
|
-
|
|
3
|
-
/*
|
|
4
|
-
* Exit Status for pgrep and pkill (`man pkill`)
|
|
5
|
-
* 0. One or more processes matched the criteria.
|
|
6
|
-
* 1. No processes matched.
|
|
7
|
-
* 2. Syntax error in the command line.
|
|
8
|
-
* 3. Fatal error: out of memory etc.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
async function getProcessIds(appName) {
|
|
12
|
-
let pids;
|
|
13
|
-
try {
|
|
14
|
-
let {stdout} = await exec('pgrep', ['-x', appName]);
|
|
15
|
-
pids = stdout
|
|
16
|
-
.trim()
|
|
17
|
-
.split('\n')
|
|
18
|
-
.map((pid) => parseInt(pid, 10));
|
|
19
|
-
} catch (err) {
|
|
20
|
-
if (parseInt(err.code, 10) !== 1) {
|
|
21
|
-
throw new Error(`Error getting process ids for app '${appName}': ${err.message}`);
|
|
22
|
-
}
|
|
23
|
-
pids = [];
|
|
24
|
-
}
|
|
25
|
-
return pids;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async function killProcess(appName, force = false) {
|
|
29
|
-
let pids = await getProcessIds(appName);
|
|
30
|
-
if (pids.length === 0) {
|
|
31
|
-
// the process is not running
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
let args = force ? ['-9'] : [];
|
|
37
|
-
args.push('-x', appName);
|
|
38
|
-
await exec('pkill', args);
|
|
39
|
-
} catch (err) {
|
|
40
|
-
if (parseInt(err.code, 10) !== 1) {
|
|
41
|
-
throw new Error(`Error killing app '${appName}' with pkill: ${err.message}`);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export {getProcessIds, killProcess};
|
package/lib/system.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import {exec} from 'teen_process';
|
|
2
|
-
import _ from 'lodash';
|
|
3
|
-
import os from 'os';
|
|
4
|
-
|
|
5
|
-
const VERSION_PATTERN = /^(\d+\.\d+)/m;
|
|
6
|
-
|
|
7
|
-
function isWindows() {
|
|
8
|
-
return os.type() === 'Windows_NT';
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function isMac() {
|
|
12
|
-
return os.type() === 'Darwin';
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function isLinux() {
|
|
16
|
-
return !isWindows() && !isMac();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function isOSWin64() {
|
|
20
|
-
return process.arch === 'x64' || _.has(process.env, 'PROCESSOR_ARCHITEW6432');
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async function arch() {
|
|
24
|
-
if (isLinux() || isMac()) {
|
|
25
|
-
let {stdout} = await exec('uname', ['-m']);
|
|
26
|
-
return stdout.trim() === 'i686' ? '32' : '64';
|
|
27
|
-
} else if (isWindows()) {
|
|
28
|
-
let is64 = this.isOSWin64();
|
|
29
|
-
return is64 ? '64' : '32';
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async function macOsxVersion() {
|
|
34
|
-
let stdout;
|
|
35
|
-
try {
|
|
36
|
-
stdout = (await exec('sw_vers', ['-productVersion'])).stdout.trim();
|
|
37
|
-
} catch (err) {
|
|
38
|
-
throw new Error(`Could not detect Mac OS X Version: ${err}`);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const versionMatch = VERSION_PATTERN.exec(stdout);
|
|
42
|
-
if (!versionMatch) {
|
|
43
|
-
throw new Error(`Could not detect Mac OS X Version from sw_vers output: '${stdout}'`);
|
|
44
|
-
}
|
|
45
|
-
return versionMatch[1];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export {isWindows, isMac, isLinux, isOSWin64, arch, macOsxVersion};
|