Socket
Socket
Sign inDemoInstall

native-run

Package Overview
Dependencies
47
Maintainers
4
Versions
55
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.1.0 to 1.2.0

17

CHANGELOG.md

@@ -0,1 +1,18 @@

# [1.2.0](https://github.com/ionic-team/native-run/compare/v1.1.0...v1.2.0) (2020-09-28)
### Bug Fixes
* **iOS:** implement iOS 14 compatibility ([#157](https://github.com/ionic-team/native-run/issues/157)) ([6f242fd](https://github.com/ionic-team/native-run/commit/6f242fd9aa1dea2cd96db13f21b981b21953f3ea))
### Features
* **android:** gracefully handle when device is offline ([aa6688d](https://github.com/ionic-team/native-run/commit/aa6688d257127c5cf6b24279a6eb506cf5b8c258))
* **android:** gracefully handle when device is out of space ([9da9f59](https://github.com/ionic-team/native-run/commit/9da9f5968cebdc7887230f3085dfd7c2d5a4f3ec))
* **android:** handle INSTALL_FAILED_INSUFFICIENT_STORAGE adb error ([bcf2369](https://github.com/ionic-team/native-run/commit/bcf2369b51e6afcd3230eb68db965fe2a89300e1))
* **android:** kill unresponsive adb server after 5s and retry ([9e1bbc7](https://github.com/ionic-team/native-run/commit/9e1bbc7d636a266ed472e6b43553781bc7e90896))
* **list:** show model, then ID if no name ([d56415d](https://github.com/ionic-team/native-run/commit/d56415d00c68ce288d6575ebf4cb0386f6070801))
* columnize `--list` output ([5b7da72](https://github.com/ionic-team/native-run/commit/5b7da7235c23b01185d8317bf5e4cdad878a9845))
# [1.1.0](https://github.com/ionic-team/native-run/compare/v1.0.0...v1.1.0) (2020-09-10)

@@ -2,0 +19,0 @@

10

dist/android/sdk-info.js

@@ -42,4 +42,10 @@ "use strict";

API Level: ${platform.apiLevel}
Packages: ${platform.packages.map(p => formatPackage(p)).join('\n' + ' '.repeat(22))}
${platform.missingPackages.length > 0 ? `(!) Missing Packages: ${platform.missingPackages.map(p => formatPackage(p)).join('\n' + ' '.repeat(22))}` : ''}
Packages: ${platform.packages
.map(p => formatPackage(p))
.join('\n' + ' '.repeat(22))}
${platform.missingPackages.length > 0
? `(!) Missing Packages: ${platform.missingPackages
.map(p => formatPackage(p))
.join('\n' + ' '.repeat(22))}`
: ''}
`.trim();

@@ -46,0 +52,0 @@ }

161

dist/android/utils/adb.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.unforwardPorts = exports.forwardPorts = exports.parseAdbDevices = exports.startActivity = exports.parseAdbInstallOutput = exports.ADBEvent = exports.uninstallApp = exports.closeApp = exports.installApk = exports.waitForClose = exports.waitForBoot = exports.waitForDevice = exports.getDeviceProperties = exports.getDeviceProperty = exports.getDevices = void 0;
exports.execAdb = exports.unforwardPorts = exports.forwardPorts = exports.parseAdbDevices = exports.startActivity = exports.parseAdbInstallOutput = exports.ADBEvent = exports.uninstallApp = exports.closeApp = exports.installApk = exports.waitForClose = exports.waitForBoot = exports.waitForDevice = exports.getDeviceProperties = exports.getDeviceProperty = exports.getDevices = void 0;
const child_process_1 = require("child_process");

@@ -22,7 +22,5 @@ const Debug = require("debug");

const debug = Debug(`${modulePrefix}:${getDevices.name}`);
const platformTools = await sdk_1.getSDKPackage(path.join(sdk.root, 'platform-tools'));
const adbBin = path.join(platformTools.location, 'adb');
const args = ['devices', '-l'];
debug('Invoking adb: %O %O', adbBin, args);
const { stdout } = await process_1.execFile(adbBin, args, { env: sdk_1.supplementProcessEnv(sdk) });
debug('Invoking adb with args: %O', args);
const stdout = await execAdb(sdk, args, { timeout: 5000 });
const devices = parseAdbDevices(stdout);

@@ -44,7 +42,5 @@ await Promise.all(devices.map(async (device) => {

const debug = Debug(`${modulePrefix}:${getDeviceProperty.name}`);
const platformTools = await sdk_1.getSDKPackage(path.join(sdk.root, 'platform-tools'));
const adbBin = path.join(platformTools.location, 'adb');
const args = ['-s', device.serial, 'shell', 'getprop', property];
debug('Invoking adb: %O %O', adbBin, args);
const { stdout } = await process_1.execFile(adbBin, args, { env: sdk_1.supplementProcessEnv(sdk) });
debug('Invoking adb with args: %O', args);
const stdout = await execAdb(sdk, args, { timeout: 5000 });
return stdout.trim();

@@ -55,9 +51,7 @@ }

const debug = Debug(`${modulePrefix}:${getDeviceProperties.name}`);
const re = /^\[([a-z0-9\.]+)\]: \[(.*)\]$/;
const platformTools = await sdk_1.getSDKPackage(path.join(sdk.root, 'platform-tools'));
const adbBin = path.join(platformTools.location, 'adb');
const args = ['-s', device.serial, 'shell', 'getprop'];
debug('Invoking adb: %O %O', adbBin, args);
debug('Invoking adb with args: %O', args);
const stdout = await execAdb(sdk, args, { timeout: 5000 });
const re = /^\[([a-z0-9.]+)\]: \[(.*)\]$/;
const propAllowList = [...ADB_GETPROP_MAP.keys()];
const { stdout } = await process_1.execFile(adbBin, args, { env: sdk_1.supplementProcessEnv(sdk) });
const properties = {};

@@ -78,7 +72,5 @@ for (const line of stdout.split(os.EOL)) {

const debug = Debug(`${modulePrefix}:${waitForDevice.name}`);
const platformTools = await sdk_1.getSDKPackage(path.join(sdk.root, 'platform-tools'));
const adbBin = path.join(platformTools.location, 'adb');
const args = ['-s', serial, 'wait-for-any-device'];
debug('Invoking adb: %O %O', adbBin, args);
await process_1.execFile(adbBin, args, { env: sdk_1.supplementProcessEnv(sdk) });
debug('Invoking adb with args: %O', args);
await execAdb(sdk, args);
debug('Device %s is connected to ADB!', serial);

@@ -103,10 +95,8 @@ }

const debug = Debug(`${modulePrefix}:${waitForClose.name}`);
const platformTools = await sdk_1.getSDKPackage(path.join(sdk.root, 'platform-tools'));
const adbBin = path.join(platformTools.location, 'adb');
const args = ['-s', device.serial, 'shell', `ps | grep ${app}`];
return new Promise(resolve => {
const interval = setInterval(async () => {
debug('Invoking adb: %O %O', adbBin, args);
try {
await process_1.execFile(adbBin, args, { env: sdk_1.supplementProcessEnv(sdk) });
debug('Invoking adb with args: %O', args);
await execAdb(sdk, args);
}

@@ -128,4 +118,7 @@ catch (e) {

const args = ['-s', device.serial, 'install', '-r', '-t', apk];
debug('Invoking adb: %O %O', adbBin, args);
const p = child_process_1.spawn(adbBin, args, { stdio: 'pipe', env: sdk_1.supplementProcessEnv(sdk) });
debug('Invoking adb with args: %O', args);
const p = child_process_1.spawn(adbBin, args, {
stdio: 'pipe',
env: sdk_1.supplementProcessEnv(sdk),
});
return new Promise((resolve, reject) => {

@@ -160,2 +153,8 @@ p.on('close', code => {

}
else if (event === ADBEvent.NotEnoughSpace) {
reject(new errors_1.ADBException(`Encountered adb error: ${ADBEvent[event]}.`, errors_1.ERR_NOT_ENOUGH_SPACE));
}
else if (event === ADBEvent.DeviceOffline) {
reject(new errors_1.ADBException(`Encountered adb error: ${ADBEvent[event]}.`, errors_1.ERR_DEVICE_OFFLINE));
}
cb();

@@ -168,7 +167,5 @@ }));

const debug = Debug(`${modulePrefix}:${closeApp.name}`);
const platformTools = await sdk_1.getSDKPackage(path.join(sdk.root, 'platform-tools'));
const adbBin = path.join(platformTools.location, 'adb');
const args = ['-s', device.serial, 'shell', 'am', 'force-stop', app];
debug('Invoking adb: %O %O', adbBin, args);
await process_1.execFile(adbBin, args, { env: sdk_1.supplementProcessEnv(sdk) });
debug('Invoking adb with args: %O', args);
await execAdb(sdk, args);
}

@@ -178,7 +175,5 @@ exports.closeApp = closeApp;

const debug = Debug(`${modulePrefix}:${uninstallApp.name}`);
const platformTools = await sdk_1.getSDKPackage(path.join(sdk.root, 'platform-tools'));
const adbBin = path.join(platformTools.location, 'adb');
const args = ['-s', device.serial, 'uninstall', app];
debug('Invoking adb: %O %O', adbBin, args);
await process_1.execFile(adbBin, args, { env: sdk_1.supplementProcessEnv(sdk) });
debug('Invoking adb with args: %O', args);
await execAdb(sdk, args);
}

@@ -192,2 +187,4 @@ exports.uninstallApp = uninstallApp;

ADBEvent[ADBEvent["NoCertificates"] = 3] = "NoCertificates";
ADBEvent[ADBEvent["NotEnoughSpace"] = 4] = "NotEnoughSpace";
ADBEvent[ADBEvent["DeviceOffline"] = 5] = "DeviceOffline";
})(ADBEvent = exports.ADBEvent || (exports.ADBEvent = {}));

@@ -209,2 +206,9 @@ function parseAdbInstallOutput(line) {

}
else if (line.includes('INSTALL_FAILED_INSUFFICIENT_STORAGE') ||
line.includes('not enough space')) {
event = ADBEvent.NotEnoughSpace;
}
else if (line.includes('device offline')) {
event = ADBEvent.DeviceOffline;
}
if (typeof event !== 'undefined') {

@@ -218,7 +222,14 @@ debug('Parsed event from adb install output: %s', ADBEvent[event]);

const debug = Debug(`${modulePrefix}:${startActivity.name}`);
const platformTools = await sdk_1.getSDKPackage(path.join(sdk.root, 'platform-tools'));
const adbBin = path.join(platformTools.location, 'adb');
const args = ['-s', device.serial, 'shell', 'am', 'start', '-W', '-n', `${packageName}/${activityName}`];
debug('Invoking adb: %O %O', adbBin, args);
await process_1.execFile(adbBin, args, { env: sdk_1.supplementProcessEnv(sdk) });
const args = [
'-s',
device.serial,
'shell',
'am',
'start',
'-W',
'-n',
`${packageName}/${activityName}`,
];
debug('Invoking adb with args: %O', args);
await execAdb(sdk, args, { timeout: 5000 });
}

@@ -240,3 +251,3 @@ exports.startActivity = startActivity;

.split(/\s+/)
.map(prop => prop.includes(':') ? prop.split(':') : undefined)
.map(prop => (prop.includes(':') ? prop.split(':') : undefined))
.filter((kv) => typeof kv !== 'undefined' && kv.length >= 2)

@@ -251,3 +262,8 @@ .reduce((acc, [k, v]) => {

const isGenericDevice = (properties['device'] || '').startsWith('generic');
const type = 'usb' in properties || isIP || !serial.startsWith('emulator') || !isGenericDevice ? 'hardware' : 'emulator';
const type = 'usb' in properties ||
isIP ||
!serial.startsWith('emulator') ||
!isGenericDevice
? 'hardware'
: 'emulator';
const connection = 'usb' in properties ? 'usb' : isIP ? 'tcpip' : null;

@@ -277,17 +293,62 @@ devices.push({

const debug = Debug(`${modulePrefix}:${forwardPorts.name}`);
const platformTools = await sdk_1.getSDKPackage(path.join(sdk.root, 'platform-tools'));
const adbBin = path.join(platformTools.location, 'adb');
const args = ['-s', device.serial, 'reverse', `tcp:${ports.device}`, `tcp:${ports.host}`];
debug('Invoking adb: %O %O', adbBin, args);
await process_1.execFile(adbBin, args, { env: sdk_1.supplementProcessEnv(sdk) });
const args = [
'-s',
device.serial,
'reverse',
`tcp:${ports.device}`,
`tcp:${ports.host}`,
];
debug('Invoking adb with args: %O', args);
await execAdb(sdk, args, { timeout: 5000 });
}
exports.forwardPorts = forwardPorts;
async function unforwardPorts(sdk, device, ports) {
const debug = Debug(`${modulePrefix}:${forwardPorts.name}`);
const platformTools = await sdk_1.getSDKPackage(path.join(sdk.root, 'platform-tools'));
const adbBin = path.join(platformTools.location, 'adb');
const args = ['-s', device.serial, 'reverse', '--remove', `tcp:${ports.device}`];
debug('Invoking adb: %O %O', adbBin, args);
await process_1.execFile(adbBin, args, { env: sdk_1.supplementProcessEnv(sdk) });
const debug = Debug(`${modulePrefix}:${unforwardPorts.name}`);
const args = [
'-s',
device.serial,
'reverse',
'--remove',
`tcp:${ports.device}`,
];
debug('Invoking adb with args: %O', args);
await execAdb(sdk, args, { timeout: 5000 });
}
exports.unforwardPorts = unforwardPorts;
async function execAdb(sdk, args, options = {}) {
const debug = Debug(`${modulePrefix}:${execAdb.name}`);
let timer;
const retry = async () => {
process.stdout.write(`ADB is unresponsive after ${options.timeout}ms, killing server and retrying...\n`);
debug('ADB timeout of %O reached, killing server and retrying...', options.timeout);
debug('Invoking adb with args: %O', ['kill-server']);
await execAdb(sdk, ['kill-server']);
debug('Invoking adb with args: %O', ['start-server']);
await execAdb(sdk, ['start-server']);
debug('Retrying...');
return run();
};
const run = async () => {
const platformTools = await sdk_1.getSDKPackage(path.join(sdk.root, 'platform-tools'));
const adbBin = path.join(platformTools.location, 'adb');
const { stdout } = await process_1.execFile(adbBin, args, {
env: sdk_1.supplementProcessEnv(sdk),
});
if (timer) {
clearTimeout(timer);
timer = undefined;
}
return stdout;
};
return new Promise((resolve, reject) => {
if (options.timeout) {
timer = setTimeout(() => retry().then(resolve, reject), options.timeout);
}
run().then(resolve, err => {
if (!timer) {
reject(err);
}
});
});
}
exports.execAdb = execAdb;

@@ -12,3 +12,3 @@ "use strict";

const readStream = await openReadStream(entry);
readStream.on('error', (err) => error = err);
readStream.on('error', (err) => (error = err));
readStream.on('data', (chunk) => chunks.push(chunk));

@@ -34,5 +34,6 @@ readStream.on('end', () => zipfile.close());

const activity = application.childNodes.find((n) => n.nodeName === 'activity');
const activityName = activity.attributes.find((a) => a.name === 'name').value;
const activityName = activity.attributes.find((a) => a.name === 'name')
.value;
return { appId, activityName };
}
exports.getApkInfo = getApkInfo;

@@ -14,13 +14,18 @@ "use strict";

const modulePrefix = 'native-run:android:utils:avd';
exports.isAVDINI = (o) => o
&& typeof o['avd.ini.encoding'] === 'string'
&& typeof o['path'] === 'string'
&& typeof o['path.rel'] === 'string'
&& typeof o['target'] === 'string';
exports.isAVDConfigINI = (o) => o
&& (typeof o['avd.ini.displayname'] === 'undefined' || typeof o['avd.ini.displayname'] === 'string')
&& (typeof o['hw.lcd.density'] === 'undefined' || typeof o['hw.lcd.density'] === 'string')
&& (typeof o['hw.lcd.height'] === 'undefined' || typeof o['hw.lcd.height'] === 'string')
&& (typeof o['hw.lcd.width'] === 'undefined' || typeof o['hw.lcd.width'] === 'string')
&& (typeof o['image.sysdir.1'] === 'undefined' || typeof o['image.sysdir.1'] === 'string');
exports.isAVDINI = (o) => o &&
typeof o['avd.ini.encoding'] === 'string' &&
typeof o['path'] === 'string' &&
typeof o['path.rel'] === 'string' &&
typeof o['target'] === 'string';
exports.isAVDConfigINI = (o) => o &&
(typeof o['avd.ini.displayname'] === 'undefined' ||
typeof o['avd.ini.displayname'] === 'string') &&
(typeof o['hw.lcd.density'] === 'undefined' ||
typeof o['hw.lcd.density'] === 'string') &&
(typeof o['hw.lcd.height'] === 'undefined' ||
typeof o['hw.lcd.height'] === 'string') &&
(typeof o['hw.lcd.width'] === 'undefined' ||
typeof o['hw.lcd.width'] === 'string') &&
(typeof o['image.sysdir.1'] === 'undefined' ||
typeof o['image.sysdir.1'] === 'string');
async function getAVDINIs(sdk) {

@@ -33,5 +38,7 @@ const debug = Debug(`${modulePrefix}:${getAVDINIs.name}`);

debug('Discovered AVD ini files: %O', iniFilePaths);
const iniFiles = await Promise.all(iniFilePaths.map(async (f) => [f, await ini_1.readINI(f, exports.isAVDINI)]));
const avdInis = iniFiles
.filter((c) => typeof c[1] !== 'undefined');
const iniFiles = await Promise.all(iniFilePaths.map(async (f) => [
f,
await ini_1.readINI(f, exports.isAVDINI),
]));
const avdInis = iniFiles.filter((c) => typeof c[1] !== 'undefined');
return avdInis;

@@ -46,5 +53,11 @@ }

: id.replace(/_/g, ' ');
const screenDPI = configini['hw.lcd.density'] ? Number(configini['hw.lcd.density']) : null;
const screenWidth = configini['hw.lcd.width'] ? Number(configini['hw.lcd.width']) : null;
const screenHeight = configini['hw.lcd.height'] ? Number(configini['hw.lcd.height']) : null;
const screenDPI = configini['hw.lcd.density']
? Number(configini['hw.lcd.density'])
: null;
const screenWidth = configini['hw.lcd.width']
? Number(configini['hw.lcd.width'])
: null;
const screenHeight = configini['hw.lcd.height']
? Number(configini['hw.lcd.height'])
: null;
return {

@@ -106,3 +119,5 @@ id,

if (missingPackages.length > 0) {
throw new errors_1.AVDException(`Unsatisfied packages within API ${api.apiLevel}: ${missingPackages.map(pkg => pkg.path).join(', ')}`, errors_1.ERR_SDK_UNSATISFIED_PACKAGES, 1);
throw new errors_1.AVDException(`Unsatisfied packages within API ${api.apiLevel}: ${missingPackages
.map(pkg => pkg.path)
.join(', ')}`, errors_1.ERR_SDK_UNSATISFIED_PACKAGES, 1);
}

@@ -178,3 +193,3 @@ return createAVDSchematic(sdk, await schema.loadPartialAVDSchematic());

const stat = await utils_fs_1.statSafe(p);
if (stat && stat.isFile()) {
if (stat === null || stat === void 0 ? void 0 : stat.isFile()) {
return;

@@ -189,3 +204,3 @@ }

const stat = await utils_fs_1.statSafe(skinsrc);
if (stat && stat.isDirectory()) {
if (stat === null || stat === void 0 ? void 0 : stat.isDirectory()) {
debug('Copying skin from %s to %s', skinsrc, skinpath);

@@ -192,0 +207,0 @@ try {

@@ -245,3 +245,3 @@ "use strict";

break;
case TypedValue.TYPE_STRING:
case TypedValue.TYPE_STRING: {
const ref = this.readS32();

@@ -251,3 +251,4 @@ typedValue.value = ref > 0 ? this.strings[ref] : '';

break;
case TypedValue.TYPE_REFERENCE:
}
case TypedValue.TYPE_REFERENCE: {
const id = this.readU32();

@@ -257,2 +258,3 @@ typedValue.value = `resourceId:0x${id.toString(16)}`;

break;
}
case TypedValue.TYPE_INT_BOOLEAN:

@@ -313,4 +315,4 @@ typedValue.value = this.readS32() !== 0;

const buf = new ArrayBuffer(4);
(new Int32Array(buf))[0] = int;
return (new Float32Array(buf))[0];
new Int32Array(buf)[0] = int;
return new Float32Array(buf)[0];
}

@@ -381,5 +383,3 @@ readString(encoding) {

// debug('sorted:', sorted);
const encoding = (header.flags & StringFlags.UTF8) === StringFlags.UTF8
? 'utf-8'
: 'ucs2';
const encoding = (header.flags & StringFlags.UTF8) === StringFlags.UTF8 ? 'utf-8' : 'ucs2';
// debug('encoding:', encoding);

@@ -478,3 +478,3 @@ const stringsStart = header.startOffset + header.stringsStart;

else {
this.document = (this.parent = node);
this.document = this.parent = node;
}

@@ -481,0 +481,0 @@ this.stack.push(node);

@@ -44,7 +44,17 @@ "use strict";

debug('Invoking emulator: %O %O', emulatorBin, args);
const p = child_process_1.spawn(emulatorBin, args, { detached: true, stdio: ['ignore', 'pipe', 'pipe'], env: sdk_1.supplementProcessEnv(sdk) });
const p = child_process_1.spawn(emulatorBin, args, {
detached: true,
stdio: ['ignore', 'pipe', 'pipe'],
env: sdk_1.supplementProcessEnv(sdk),
});
p.unref();
return new Promise((_resolve, _reject) => {
const resolve = fn_1.once(() => { _resolve(); cleanup(); });
const reject = fn_1.once(err => { _reject(err); cleanup(); });
const resolve = fn_1.once(() => {
_resolve();
cleanup();
});
const reject = fn_1.once(err => {
_reject(err);
cleanup();
});
adb_1.waitForDevice(sdk, `emulator-${port}`).then(() => resolve(), err => reject(err));

@@ -127,4 +137,5 @@ const eventParser = through2((chunk, enc, cb) => {

debug('Connected to %s:%d', host, port);
utils_fs_1.readFile(path.resolve(os.homedir(), '.emulator_console_auth_token'), { encoding: 'utf8' })
.then(contents => resolve(contents.trim()), err => reject(err));
utils_fs_1.readFile(path.resolve(os.homedir(), '.emulator_console_auth_token'), {
encoding: 'utf8',
}).then(contents => resolve(contents.trim()), err => reject(err));
});

@@ -158,3 +169,4 @@ });

debug('Android Console: %O', line);
if (stage === Stage.Initial && line.includes('Authentication required')) {
if (stage === Stage.Initial &&
line.includes('Authentication required')) {
stage = Stage.Auth;

@@ -161,0 +173,0 @@ }

@@ -27,5 +27,2 @@ "use strict";

id: device.serial,
format() {
return `${this.model} (API ${this.sdkVersion}) ${this.id}`;
},
};

@@ -40,7 +37,4 @@ }

id: avd.id,
format() {
return `${this.name} (API ${this.sdkVersion}) ${this.id}`;
},
};
}
exports.avdToTarget = avdToTarget;

@@ -81,3 +81,4 @@ "use strict";

if (e instanceof errors_1.ADBException) {
if (e.code === errors_1.ERR_INCOMPATIBLE_UPDATE || e.code === errors_1.ERR_VERSION_DOWNGRADE) {
if (e.code === errors_1.ERR_INCOMPATIBLE_UPDATE ||
e.code === errors_1.ERR_VERSION_DOWNGRADE) {
process.stdout.write(`${e.message} Uninstalling and trying again...\n`);

@@ -84,0 +85,0 @@ await adb_1.uninstallApp(sdk, device, appId);

@@ -12,3 +12,3 @@ "use strict";

.filter((apiLevel) => typeof apiLevel !== 'undefined')),
].sort((a, b) => a <= b ? 1 : -1);
].sort((a, b) => (a <= b ? 1 : -1));
const apis = levels.map(apiLevel => ({

@@ -56,3 +56,7 @@ apiLevel,

{ name: 'Android Emulator', path: 'emulator', version: /.+/ },
{ name: 'Android SDK Platform 29', path: 'platforms;android-29', version: /.+/ },
{
name: 'Android SDK Platform 29',
path: 'platforms;android-29',
version: /.+/,
},
];

@@ -76,3 +80,7 @@ const missingPackages = findUnsatisfiedPackages(packages, schemas);

{ name: 'Android Emulator', path: 'emulator', version: /.+/ },
{ name: 'Android SDK Platform 28', path: 'platforms;android-28', version: /.+/ },
{
name: 'Android SDK Platform 28',
path: 'platforms;android-28',
version: /.+/,
},
];

@@ -96,3 +104,7 @@ const missingPackages = findUnsatisfiedPackages(packages, schemas);

{ name: 'Android Emulator', path: 'emulator', version: /.+/ },
{ name: 'Android SDK Platform 27', path: 'platforms;android-27', version: /.+/ },
{
name: 'Android SDK Platform 27',
path: 'platforms;android-27',
version: /.+/,
},
];

@@ -116,3 +128,7 @@ const missingPackages = findUnsatisfiedPackages(packages, schemas);

{ name: 'Android Emulator', path: 'emulator', version: /.+/ },
{ name: 'Android SDK Platform 26', path: 'platforms;android-26', version: /.+/ },
{
name: 'Android SDK Platform 26',
path: 'platforms;android-26',
version: /.+/,
},
];

@@ -136,3 +152,7 @@ const missingPackages = findUnsatisfiedPackages(packages, schemas);

{ name: 'Android Emulator', path: 'emulator', version: /.+/ },
{ name: 'Android SDK Platform 25', path: 'platforms;android-25', version: /.+/ },
{
name: 'Android SDK Platform 25',
path: 'platforms;android-25',
version: /.+/,
},
];

@@ -156,3 +176,7 @@ const missingPackages = findUnsatisfiedPackages(packages, schemas);

{ name: 'Android Emulator', path: 'emulator', version: /.+/ },
{ name: 'Android SDK Platform 24', path: 'platforms;android-24', version: /.+/ },
{
name: 'Android SDK Platform 24',
path: 'platforms;android-24',
version: /.+/,
},
];

@@ -159,0 +183,0 @@ const missingPackages = findUnsatisfiedPackages(packages, schemas);

@@ -16,3 +16,8 @@ "use strict";

['linux', [pathlib.join(homedir, 'Android', 'sdk')]],
['win32', [pathlib.join(process.env.LOCALAPPDATA || pathlib.join(homedir, 'AppData', 'Local'), 'Android', 'Sdk')]],
[
'win32',
[
pathlib.join(process.env.LOCALAPPDATA || pathlib.join(homedir, 'AppData', 'Local'), 'Android', 'Sdk'),
],
],
]);

@@ -62,6 +67,4 @@ async function getSDK() {

});
sdk.packages = await Promise.all(contents
.map(p => pathlib.dirname(p))
.map(p => getSDKPackage(p)));
sdk.packages.sort((a, b) => a.name >= b.name ? 1 : -1);
sdk.packages = await Promise.all(contents.map(p => pathlib.dirname(p)).map(p => getSDKPackage(p)));
sdk.packages.sort((a, b) => (a.name >= b.name ? 1 : -1));
return sdk.packages;

@@ -107,3 +110,3 @@ }

// defined and valid.
if (process.env.ANDROID_HOME && await fs_1.isDir(process.env.ANDROID_HOME)) {
if (process.env.ANDROID_HOME && (await fs_1.isDir(process.env.ANDROID_HOME))) {
debug('Using $ANDROID_HOME at %s', process.env.ANDROID_HOME);

@@ -114,3 +117,4 @@ return process.env.ANDROID_HOME;

// No valid $ANDROID_HOME, try $ANDROID_SDK_ROOT.
if (process.env.ANDROID_SDK_ROOT && await fs_1.isDir(process.env.ANDROID_SDK_ROOT)) {
if (process.env.ANDROID_SDK_ROOT &&
(await fs_1.isDir(process.env.ANDROID_SDK_ROOT))) {
debug('Using $ANDROID_SDK_ROOT at %s', process.env.ANDROID_SDK_ROOT);

@@ -136,3 +140,4 @@ return process.env.ANDROID_SDK_ROOT;

debug('Looking for $ANDROID_EMULATOR_HOME');
if (process.env.ANDROID_EMULATOR_HOME && await fs_1.isDir(process.env.ANDROID_EMULATOR_HOME)) {
if (process.env.ANDROID_EMULATOR_HOME &&
(await fs_1.isDir(process.env.ANDROID_EMULATOR_HOME))) {
debug('Using $ANDROID_EMULATOR_HOME at %s', process.env.$ANDROID_EMULATOR_HOME);

@@ -153,3 +158,4 @@ return process.env.ANDROID_EMULATOR_HOME;

debug('Looking for $ANDROID_AVD_HOME');
if (process.env.ANDROID_AVD_HOME && await fs_1.isDir(process.env.ANDROID_AVD_HOME)) {
if (process.env.ANDROID_AVD_HOME &&
(await fs_1.isDir(process.env.ANDROID_AVD_HOME))) {
debug('Using $ANDROID_AVD_HOME at %s', process.env.$ANDROID_AVD_HOME);

@@ -156,0 +162,0 @@ return process.env.ANDROID_AVD_HOME;

@@ -7,4 +7,5 @@ "use strict";

function getAPILevelFromPackageXml(packageXml) {
var _a;
const apiLevel = packageXml.find('./localPackage/type-details/api-level');
return apiLevel && apiLevel.text ? apiLevel.text.toString() : undefined;
return (_a = apiLevel === null || apiLevel === void 0 ? void 0 : apiLevel.text) === null || _a === void 0 ? void 0 : _a.toString();
}

@@ -45,3 +46,3 @@ exports.getAPILevelFromPackageXml = getAPILevelFromPackageXml;

];
const textFromElement = (e) => e && e.text ? e.text.toString() : '';
const textFromElement = (e) => (e === null || e === void 0 ? void 0 : e.text) ? e.text.toString() : '';
const versions = [];

@@ -48,0 +49,0 @@ for (const version of versionElements.map(textFromElement)) {

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.serializeError = exports.IOSRunException = exports.SDKException = exports.AndroidRunException = exports.EmulatorException = exports.AVDException = exports.ADBException = exports.CLIException = exports.ERR_UNSUPPORTED_API_LEVEL = exports.ERR_UNKNOWN_AVD = exports.ERR_NO_TARGET = exports.ERR_NO_DEVICE = exports.ERR_TARGET_NOT_FOUND = exports.ERR_SDK_UNSATISFIED_PACKAGES = exports.ERR_SDK_PACKAGE_NOT_FOUND = exports.ERR_SDK_NOT_FOUND = exports.ERR_UNSUITABLE_API_INSTALLATION = exports.ERR_MISSING_SYSTEM_IMAGE = exports.ERR_NO_AVDS_FOUND = exports.ERR_NON_ZERO_EXIT = exports.ERR_INVALID_SYSTEM_IMAGE = exports.ERR_INVALID_SKIN = exports.ERR_INVALID_SERIAL = exports.ERR_INVALID_SDK_PACKAGE = exports.ERR_NO_CERTIFICATES = exports.ERR_MIN_SDK_VERSION = exports.ERR_VERSION_DOWNGRADE = exports.ERR_INCOMPATIBLE_UPDATE = exports.ERR_EMULATOR_HOME_NOT_FOUND = exports.ERR_AVD_HOME_NOT_FOUND = exports.ERR_ALREADY_RUNNING = exports.ERR_BAD_INPUT = exports.AndroidException = exports.Exception = void 0;
exports.serializeError = exports.IOSRunException = exports.SDKException = exports.AndroidRunException = exports.EmulatorException = exports.AVDException = exports.ADBException = exports.CLIException = exports.ERR_UNSUPPORTED_API_LEVEL = exports.ERR_UNKNOWN_AVD = exports.ERR_NO_TARGET = exports.ERR_NO_DEVICE = exports.ERR_TARGET_NOT_FOUND = exports.ERR_SDK_UNSATISFIED_PACKAGES = exports.ERR_SDK_PACKAGE_NOT_FOUND = exports.ERR_SDK_NOT_FOUND = exports.ERR_UNSUITABLE_API_INSTALLATION = exports.ERR_MISSING_SYSTEM_IMAGE = exports.ERR_NO_AVDS_FOUND = exports.ERR_NON_ZERO_EXIT = exports.ERR_INVALID_SYSTEM_IMAGE = exports.ERR_INVALID_SKIN = exports.ERR_INVALID_SERIAL = exports.ERR_INVALID_SDK_PACKAGE = exports.ERR_DEVICE_OFFLINE = exports.ERR_NOT_ENOUGH_SPACE = exports.ERR_NO_CERTIFICATES = exports.ERR_MIN_SDK_VERSION = exports.ERR_VERSION_DOWNGRADE = exports.ERR_INCOMPATIBLE_UPDATE = exports.ERR_EMULATOR_HOME_NOT_FOUND = exports.ERR_AVD_HOME_NOT_FOUND = exports.ERR_ALREADY_RUNNING = exports.ERR_BAD_INPUT = exports.AndroidException = exports.Exception = void 0;
const json_1 = require("./utils/json");

@@ -41,2 +41,4 @@ class Exception extends Error {

exports.ERR_NO_CERTIFICATES = 'ERR_NO_CERTIFICATES';
exports.ERR_NOT_ENOUGH_SPACE = 'ERR_NOT_ENOUGH_SPACE';
exports.ERR_DEVICE_OFFLINE = 'ERR_DEVICE_OFFLINE';
exports.ERR_INVALID_SDK_PACKAGE = 'ERR_INVALID_SDK_PACKAGE';

@@ -43,0 +45,0 @@ exports.ERR_INVALID_SERIAL = 'ERR_INVALID_SERIAL';

@@ -31,3 +31,7 @@ "use strict";

else {
if (!platform || platform === 'help' || args.includes('--help') || args.includes('-h') || platform.startsWith('-')) {
if (!platform ||
platform === 'help' ||
args.includes('--help') ||
args.includes('-h') ||
platform.startsWith('-')) {
cmd = await Promise.resolve().then(() => require('./help'));

@@ -34,0 +38,0 @@ return cmd.run(args);

@@ -24,3 +24,2 @@ "use strict";

--app <path> ......... Deploy specified .app or .ipa file

@@ -27,0 +26,0 @@ --device ............. Use a device if available

@@ -53,3 +53,6 @@ "use strict";

toCString(path).copy(data, 8);
const resp = await this.protocolClient.sendMessage({ operation: afc_1.AFC_OPS.FILE_OPEN, data });
const resp = await this.protocolClient.sendMessage({
operation: afc_1.AFC_OPS.FILE_OPEN,
data,
});
if (resp.operation === afc_1.AFC_OPS.FILE_OPEN_RES) {

@@ -120,3 +123,4 @@ return resp.data;

numOpenFiles++;
_this.uploadFile(filePath, remotePath)
_this
.uploadFile(filePath, remotePath)
.then(() => {

@@ -123,0 +127,0 @@ resolve();

@@ -26,10 +26,15 @@ "use strict";

async lookupApp(bundleIds, options = {
'ReturnAttributes': ['Path', 'Container', 'CFBundleExecutable', 'CFBundleIdentifier'],
'ApplicationsType': 'Any',
ReturnAttributes: [
'Path',
'Container',
'CFBundleExecutable',
'CFBundleIdentifier',
],
ApplicationsType: 'Any',
}) {
debug(`lookupApp, options: ${JSON.stringify(options)}`);
const resp = await this.protocolClient.sendMessage({
'Command': 'Lookup',
'ClientOptions': {
'BundleIDs': bundleIds,
Command: 'Lookup',
ClientOptions: {
BundleIDs: bundleIds,
...options,

@@ -46,11 +51,11 @@ },

async installApp(packagePath, bundleId, options = {
'ApplicationsType': 'Any',
'PackageType': 'Developer',
ApplicationsType: 'Any',
PackageType: 'Developer',
}) {
debug(`installApp, packagePath: ${packagePath}, bundleId: ${bundleId}`);
return this.protocolClient.sendMessage({
'Command': 'Install',
'PackagePath': packagePath,
'ClientOptions': {
'CFBundleIdentifier': bundleId,
Command: 'Install',
PackagePath: packagePath,
ClientOptions: {
CFBundleIdentifier: bundleId,
...options,

@@ -57,0 +62,0 @@ },

@@ -10,3 +10,5 @@ "use strict";

function isLockdowndServiceResponse(resp) {
return resp.Request === 'StartService' && resp.Service !== undefined && resp.Port !== undefined;
return (resp.Request === 'StartService' &&
resp.Service !== undefined &&
resp.Port !== undefined);
}

@@ -20,3 +22,5 @@ function isLockdowndSessionResponse(resp) {

function isLockdowndValueResponse(resp) {
return resp.Request === 'GetValue' && resp.Key !== undefined && typeof resp.Value === 'string';
return (resp.Request === 'GetValue' &&
resp.Key !== undefined &&
typeof resp.Value === 'string');
}

@@ -34,4 +38,4 @@ function isLockdowndQueryTypeResponse(resp) {

const resp = await this.protocolClient.sendMessage({
'Request': 'StartService',
'Service': name,
Request: 'StartService',
Service: name,
});

@@ -48,5 +52,5 @@ if (isLockdowndServiceResponse(resp)) {

const resp = await this.protocolClient.sendMessage({
'Request': 'StartSession',
'HostID': pairRecord.HostID,
'SystemBUID': pairRecord.SystemBUID,
Request: 'StartSession',
HostID: pairRecord.HostID,
SystemBUID: pairRecord.SystemBUID,
});

@@ -72,3 +76,3 @@ if (isLockdowndSessionResponse(resp)) {

debug(`getAllValues`);
const resp = await this.protocolClient.sendMessage({ 'Request': 'GetValue' });
const resp = await this.protocolClient.sendMessage({ Request: 'GetValue' });
if (isLockdowndAllValuesResponse(resp)) {

@@ -84,4 +88,4 @@ return resp.Value;

const resp = await this.protocolClient.sendMessage({
'Request': 'GetValue',
'Key': val,
Request: 'GetValue',
Key: val,
});

@@ -97,3 +101,5 @@ if (isLockdowndValueResponse(resp)) {

debug('queryType');
const resp = await this.protocolClient.sendMessage({ 'Request': 'QueryType' });
const resp = await this.protocolClient.sendMessage({
Request: 'QueryType',
});
if (isLockdowndQueryTypeResponse(resp)) {

@@ -100,0 +106,0 @@ return resp.Type;

@@ -22,6 +22,6 @@ "use strict";

const resp = await this.protocolClient.sendMessage({
'Command': 'MountImage',
'ImagePath': imagePath,
'ImageSignature': imageSig,
'ImageType': 'Developer',
Command: 'MountImage',
ImagePath: imagePath,
ImageSignature: imageSig,
ImageType: 'Developer',
});

@@ -36,6 +36,6 @@ if (!lockdown_1.isLockdownResponse(resp) || resp.Status !== 'Complete') {

return this.protocolClient.sendMessage({
'Command': 'ReceiveBytes',
'ImageSize': imageSize,
'ImageSignature': imageSig,
'ImageType': 'Developer',
Command: 'ReceiveBytes',
ImageSize: imageSize,
ImageSignature: imageSig,
ImageType: 'Developer',
}, (resp, resolve, reject) => {

@@ -58,4 +58,4 @@ if (isMIMUploadReceiveBytesResponse(resp)) {

return this.protocolClient.sendMessage({
'Command': 'LookupImage',
'ImageType': 'Developer',
Command: 'LookupImage',
ImageType: 'Developer',
});

@@ -62,0 +62,0 @@ }

@@ -38,4 +38,4 @@ "use strict";

extraFields: {
'DeviceID': device.DeviceID,
'PortNumber': htons(port),
DeviceID: device.DeviceID,
PortNumber: htons(port),
},

@@ -52,3 +52,5 @@ });

debug('getDevices');
const resp = await this.protocolClient.sendMessage({ messageType: 'ListDevices' });
const resp = await this.protocolClient.sendMessage({
messageType: 'ListDevices',
});
if (isUsbmuxdDeviceResponse(resp)) {

@@ -81,3 +83,3 @@ return resp.DeviceList;

messageType: 'ReadPairRecord',
extraFields: { 'PairRecordID': udid },
extraFields: { PairRecordID: udid },
});

@@ -84,0 +86,0 @@ if (isUsbmuxdPairRecordResponse(resp)) {

@@ -55,6 +55,13 @@ "use strict";

async getDebugserverClient() {
return this.getServiceClient('com.apple.debugserver', debugserver_1.DebugserverClient, true);
try {
// iOS 14 added support for a secure debug service so try to connect to that first
return await this.getServiceClient('com.apple.debugserver.DVTSecureSocketProxy', debugserver_1.DebugserverClient);
}
catch {
// otherwise, fall back to the previous implementation
return this.getServiceClient('com.apple.debugserver', debugserver_1.DebugserverClient, true);
}
}
async getServiceClient(name, ServiceType, disableSSL = false) {
const { port: servicePort, enableServiceSSL } = await this.lockdowndClient.startService(name);
const { port: servicePort, enableServiceSSL, } = await this.lockdowndClient.startService(name);
const usbmuxClient = new usbmuxd_1.UsbmuxdClient(usbmuxd_1.UsbmuxdClient.connectUsbmuxdSocket());

@@ -80,3 +87,5 @@ let usbmuxdSocket = await usbmuxClient.connect(this.device, servicePort);

await new Promise((res, rej) => {
const timeoutId = setTimeout(() => { rej('The TLS handshake failed to complete after 5s.'); }, 5000);
const timeoutId = setTimeout(() => {
rej('The TLS handshake failed to complete after 5s.');
}, 5000);
tls.connect(tlsOptions, function () {

@@ -83,0 +92,0 @@ clearTimeout(timeoutId);

@@ -14,44 +14,167 @@ "use strict";

(function (AFC_OPS) {
/**
* Invalid
*/
AFC_OPS[AFC_OPS["INVALID"] = 0] = "INVALID";
/**
* Status
*/
AFC_OPS[AFC_OPS["STATUS"] = 1] = "STATUS";
/**
* Data
*/
AFC_OPS[AFC_OPS["DATA"] = 2] = "DATA";
/**
* ReadDir
*/
AFC_OPS[AFC_OPS["READ_DIR"] = 3] = "READ_DIR";
/**
* ReadFile
*/
AFC_OPS[AFC_OPS["READ_FILE"] = 4] = "READ_FILE";
/**
* WriteFile
*/
AFC_OPS[AFC_OPS["WRITE_FILE"] = 5] = "WRITE_FILE";
/**
* WritePart
*/
AFC_OPS[AFC_OPS["WRITE_PART"] = 6] = "WRITE_PART";
/**
* TruncateFile
*/
AFC_OPS[AFC_OPS["TRUNCATE"] = 7] = "TRUNCATE";
/**
* RemovePath
*/
AFC_OPS[AFC_OPS["REMOVE_PATH"] = 8] = "REMOVE_PATH";
/**
* MakeDir
*/
AFC_OPS[AFC_OPS["MAKE_DIR"] = 9] = "MAKE_DIR";
/**
* GetFileInfo
*/
AFC_OPS[AFC_OPS["GET_FILE_INFO"] = 10] = "GET_FILE_INFO";
/**
* GetDeviceInfo
*/
AFC_OPS[AFC_OPS["GET_DEVINFO"] = 11] = "GET_DEVINFO";
/**
* WriteFileAtomic (tmp file+rename)
*/
AFC_OPS[AFC_OPS["WRITE_FILE_ATOM"] = 12] = "WRITE_FILE_ATOM";
/**
* FileRefOpen
*/
AFC_OPS[AFC_OPS["FILE_OPEN"] = 13] = "FILE_OPEN";
/**
* FileRefOpenResult
*/
AFC_OPS[AFC_OPS["FILE_OPEN_RES"] = 14] = "FILE_OPEN_RES";
/**
* FileRefRead
*/
AFC_OPS[AFC_OPS["FILE_READ"] = 15] = "FILE_READ";
/**
* FileRefWrite
*/
AFC_OPS[AFC_OPS["FILE_WRITE"] = 16] = "FILE_WRITE";
/**
* FileRefSeek
*/
AFC_OPS[AFC_OPS["FILE_SEEK"] = 17] = "FILE_SEEK";
/**
* FileRefTell
*/
AFC_OPS[AFC_OPS["FILE_TELL"] = 18] = "FILE_TELL";
/**
* FileRefTellResult
*/
AFC_OPS[AFC_OPS["FILE_TELL_RES"] = 19] = "FILE_TELL_RES";
/**
* FileRefClose
*/
AFC_OPS[AFC_OPS["FILE_CLOSE"] = 20] = "FILE_CLOSE";
/**
* FileRefSetFileSize (ftruncate)
*/
AFC_OPS[AFC_OPS["FILE_SET_SIZE"] = 21] = "FILE_SET_SIZE";
/**
* GetConnectionInfo
*/
AFC_OPS[AFC_OPS["GET_CON_INFO"] = 22] = "GET_CON_INFO";
/**
* SetConnectionOptions
*/
AFC_OPS[AFC_OPS["SET_CON_OPTIONS"] = 23] = "SET_CON_OPTIONS";
/**
* RenamePath
*/
AFC_OPS[AFC_OPS["RENAME_PATH"] = 24] = "RENAME_PATH";
/**
* SetFSBlockSize (0x800000)
*/
AFC_OPS[AFC_OPS["SET_FS_BS"] = 25] = "SET_FS_BS";
/**
* SetSocketBlockSize (0x800000)
*/
AFC_OPS[AFC_OPS["SET_SOCKET_BS"] = 26] = "SET_SOCKET_BS";
/**
* FileRefLock
*/
AFC_OPS[AFC_OPS["FILE_LOCK"] = 27] = "FILE_LOCK";
/**
* MakeLink
*/
AFC_OPS[AFC_OPS["MAKE_LINK"] = 28] = "MAKE_LINK";
/**
* GetFileHash
*/
AFC_OPS[AFC_OPS["GET_FILE_HASH"] = 29] = "GET_FILE_HASH";
/**
* SetModTime
*/
AFC_OPS[AFC_OPS["SET_FILE_MOD_TIME"] = 30] = "SET_FILE_MOD_TIME";
/**
* GetFileHashWithRange
*/
AFC_OPS[AFC_OPS["GET_FILE_HASH_RANGE"] = 31] = "GET_FILE_HASH_RANGE";
/* iOS 6+ */
// iOS 6+
/**
* FileRefSetImmutableHint
*/
AFC_OPS[AFC_OPS["FILE_SET_IMMUTABLE_HINT"] = 32] = "FILE_SET_IMMUTABLE_HINT";
/**
* GetSizeOfPathContents
*/
AFC_OPS[AFC_OPS["GET_SIZE_OF_PATH_CONTENTS"] = 33] = "GET_SIZE_OF_PATH_CONTENTS";
/**
* RemovePathAndContents
*/
AFC_OPS[AFC_OPS["REMOVE_PATH_AND_CONTENTS"] = 34] = "REMOVE_PATH_AND_CONTENTS";
/**
* DirectoryEnumeratorRefOpen
*/
AFC_OPS[AFC_OPS["DIR_OPEN"] = 35] = "DIR_OPEN";
/**
* DirectoryEnumeratorRefOpenResult
*/
AFC_OPS[AFC_OPS["DIR_OPEN_RESULT"] = 36] = "DIR_OPEN_RESULT";
/**
* DirectoryEnumeratorRefRead
*/
AFC_OPS[AFC_OPS["DIR_READ"] = 37] = "DIR_READ";
/**
* DirectoryEnumeratorRefClose
*/
AFC_OPS[AFC_OPS["DIR_CLOSE"] = 38] = "DIR_CLOSE";
/* iOS 7+ */
// iOS 7+
/**
* FileRefReadWithOffset
*/
AFC_OPS[AFC_OPS["FILE_READ_OFFSET"] = 39] = "FILE_READ_OFFSET";
/**
* FileRefWriteWithOffset
*/
AFC_OPS[AFC_OPS["FILE_WRITE_OFFSET"] = 40] = "FILE_WRITE_OFFSET";

@@ -96,11 +219,31 @@ })(AFC_OPS = exports.AFC_OPS || (exports.AFC_OPS = {}));

(function (AFC_FILE_OPEN_FLAGS) {
/**
* r (O_RDONLY)
*/
AFC_FILE_OPEN_FLAGS[AFC_FILE_OPEN_FLAGS["RDONLY"] = 1] = "RDONLY";
/**
* r+ (O_RDWR | O_CREAT)
*/
AFC_FILE_OPEN_FLAGS[AFC_FILE_OPEN_FLAGS["RW"] = 2] = "RW";
/**
* w (O_WRONLY | O_CREAT | O_TRUNC)
*/
AFC_FILE_OPEN_FLAGS[AFC_FILE_OPEN_FLAGS["WRONLY"] = 3] = "WRONLY";
/**
* w+ (O_RDWR | O_CREAT | O_TRUNC)
*/
AFC_FILE_OPEN_FLAGS[AFC_FILE_OPEN_FLAGS["WR"] = 4] = "WR";
/**
* a (O_WRONLY | O_APPEND | O_CREAT)
*/
AFC_FILE_OPEN_FLAGS[AFC_FILE_OPEN_FLAGS["APPEND"] = 5] = "APPEND";
/**
* a+ (O_RDWR | O_APPEND | O_CREAT)
*/
AFC_FILE_OPEN_FLAGS[AFC_FILE_OPEN_FLAGS["RDAPPEND"] = 6] = "RDAPPEND";
})(AFC_FILE_OPEN_FLAGS = exports.AFC_FILE_OPEN_FLAGS || (exports.AFC_FILE_OPEN_FLAGS = {}));
function isAFCResponse(resp) {
return AFC_OPS[resp.operation] !== undefined && resp.id !== undefined && resp.data !== undefined;
return (AFC_OPS[resp.operation] !== undefined &&
resp.id !== undefined &&
resp.data !== undefined);
}

@@ -107,0 +250,0 @@ function isStatusResponse(resp) {

@@ -18,2 +18,35 @@ "use strict";

}
onData(data) {
// the GDB protocol does not support body length in its header so we cannot rely on
// the parent implementation to determine when a payload is complete
try {
// if there's data, add it to the existing buffer
this.buffer = data ? Buffer.concat([this.buffer, data]) : this.buffer;
// do we have enough bytes to proceed
if (this.buffer.length < this.headerSize) {
return; // incomplete header, wait for more
}
// first, check the header
if (this.parseHeader(this.buffer) === -1) {
// we have a valid header so check the body. GDB packets will always be a leading '$', data bytes,
// a trailing '#', and a two digit checksum. minimum valid body is the empty response '$#00'
// https://developer.apple.com/library/archive/documentation/DeveloperTools/gdb/gdb/gdb_33.html
const packetData = this.buffer.toString().match('\\$.*#[0-9a-f]{2}');
if (packetData == null) {
return; // incomplete body, wait for more
}
// extract the body and update the buffer
const body = Buffer.from(packetData[0]);
this.buffer = this.buffer.slice(this.headerSize + body.length);
// parse the payload and recurse if there is more data to process
this.callback(this.parseBody(body));
if (this.buffer.length) {
this.onData();
}
}
}
catch (err) {
this.callback(null, err);
}
}
parseHeader(data) {

@@ -40,3 +73,3 @@ if (data[0] !== ACK_SUCCESS) {

else {
throw new Error('Didn\'t receive checksum');
throw new Error("Didn't receive checksum");
}

@@ -51,3 +84,6 @@ }

// hex encode and concat all args
const encodedArgs = args.map(arg => Buffer.from(arg).toString('hex')).join().toUpperCase();
const encodedArgs = args
.map(arg => Buffer.from(arg).toString('hex'))
.join()
.toUpperCase();
const checksumStr = calculateChecksum(cmd + encodedArgs);

@@ -54,0 +90,0 @@ const formattedCmd = `$${cmd}${encodedArgs}#${checksumStr}`;

@@ -93,3 +93,6 @@ "use strict";

if (callback) {
callback(resp, (...args) => { this.socket.removeListener('data', reader.onData); resolve(...args); }, reject);
callback(resp, (...args) => {
this.socket.removeListener('data', reader.onData);
resolve(...args);
}, reject);
}

@@ -96,0 +99,0 @@ else {

@@ -34,10 +34,11 @@ "use strict";

write(socket, msg) {
// TODO Usbmux message type
debug(`socket write: ${JSON.stringify(msg)}`);
const { messageType, extraFields } = msg;
const plistMessage = plist.build({
'BundleID': 'io.ionic.native-run',
'ClientVersionString': 'usbmux.js',
'MessageType': messageType,
'ProgName': 'native-run',
'kLibUSBMuxVersion': 3,
BundleID: 'io.ionic.native-run',
ClientVersionString: 'usbmux.js',
MessageType: messageType,
ProgName: 'native-run',
kLibUSBMuxVersion: 3,
...extraFields,

@@ -44,0 +45,0 @@ });

@@ -46,5 +46,2 @@ "use strict";

id: device.UniqueDeviceID,
format() {
return `${this.name} ${this.model} ${this.sdkVersion} ${this.id}`;
},
};

@@ -58,6 +55,3 @@ }

id: simulator.udid,
format() {
return `${this.name} ${this.sdkVersion} ${this.id}`;
},
};
}

@@ -43,4 +43,6 @@ "use strict";

const readStream = await openReadStream(entry);
readStream.on('error', (err) => error = err);
readStream.on('end', () => { zipfile.readEntry(); });
readStream.on('error', (err) => (error = err));
readStream.on('end', () => {
zipfile.readEntry();
});
readStream.pipe(fs_1.createWriteStream(dest));

@@ -47,0 +49,0 @@ }

@@ -11,3 +11,5 @@ "use strict";

async function getSimulators() {
const simctl = child_process_1.spawnSync('xcrun', ['simctl', 'list', '--json'], { encoding: 'utf8' });
const simctl = child_process_1.spawnSync('xcrun', ['simctl', 'list', '--json'], {
encoding: 'utf8',
});
if (simctl.status) {

@@ -23,3 +25,4 @@ throw new errors_1.Exception(`Unable to retrieve simulator list: ${simctl.stderr}`);

return output.runtimes
.filter(runtime => runtime.name.indexOf('watch') === -1 && runtime.name.indexOf('tv') === -1)
.filter(runtime => runtime.name.indexOf('watch') === -1 &&
runtime.name.indexOf('tv') === -1)
.map(runtime => (output.devices[runtime.identifier] || output.devices[runtime.name])

@@ -29,3 +32,3 @@ .filter(device => device.isAvailable)

.reduce((prev, next) => prev.concat(next)) // flatten
.sort((a, b) => a.name < b.name ? -1 : 1);
.sort((a, b) => (a.name < b.name ? -1 : 1));
}

@@ -39,5 +42,8 @@ catch (err) {

debug(`Booting simulator ${udid}`);
const bootResult = child_process_1.spawnSync('xcrun', ['simctl', 'boot', udid], { encoding: 'utf8' });
const bootResult = child_process_1.spawnSync('xcrun', ['simctl', 'boot', udid], {
encoding: 'utf8',
});
// TODO: is there a better way to check this?
if (bootResult.status && !bootResult.stderr.includes('Unable to boot device in current state: Booted')) {
if (bootResult.status &&
!bootResult.stderr.includes('Unable to boot device in current state: Booted')) {
throw new errors_1.Exception(`There was an error booting simulator: ${bootResult.stderr}`);

@@ -52,3 +58,8 @@ }

debug(`Running simulator ${udid}`);
const openResult = child_process_1.spawnSync('open', [`${xCodePath}/Applications/Simulator.app`, '--args', '-CurrentDeviceUDID', udid], { encoding: 'utf8' });
const openResult = child_process_1.spawnSync('open', [
`${xCodePath}/Applications/Simulator.app`,
'--args',
'-CurrentDeviceUDID',
udid,
], { encoding: 'utf8' });
if (openResult.status) {

@@ -55,0 +66,0 @@ throw new errors_1.Exception(`There was an error opening simulator: ${openResult.stderr}`);

@@ -9,3 +9,5 @@ "use strict";

function getXcodeVersionInfo() {
const xcodeVersionInfo = child_process_1.spawnSync('xcodebuild', ['-version'], { encoding: 'utf8' });
const xcodeVersionInfo = child_process_1.spawnSync('xcodebuild', ['-version'], {
encoding: 'utf8',
});
if (xcodeVersionInfo.error) {

@@ -25,3 +27,5 @@ throw xcodeVersionInfo.error;

try {
const { stdout } = await process_1.execFile('xcode-select', ['-p'], { encoding: 'utf8' });
const { stdout } = await process_1.execFile('xcode-select', ['-p'], {
encoding: 'utf8',
});
if (stdout) {

@@ -28,0 +32,0 @@ return stdout.trim();

@@ -7,3 +7,3 @@ "use strict";

const stats = await utils_fs_1.statSafe(p);
if (stats && stats.isDirectory()) {
if (stats === null || stats === void 0 ? void 0 : stats.isDirectory()) {
return true;

@@ -10,0 +10,0 @@ }

@@ -5,4 +5,4 @@ "use strict";

function stringify(obj) {
return JSON.stringify(obj, (k, v) => v instanceof RegExp ? v.toString() : v, '\t');
return JSON.stringify(obj, (k, v) => (v instanceof RegExp ? v.toString() : v), '\t');
}
exports.stringify = stringify;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatTargets = void 0;
const utils_terminal_1 = require("@ionic/utils-terminal");
const errors_1 = require("../errors");

@@ -47,7 +48,23 @@ const json_1 = require("./json");

else {
for (const target of targets) {
output += ` ${(target.format())}\n`;
}
output += formatTargetTable(targets) + '\n';
}
return output;
}
function formatTargetTable(targets) {
const spacer = utils_terminal_1.indent(2);
return (spacer +
utils_terminal_1.columnar(targets.map(targetToRow), {
headers: ['Name', 'API', 'Target ID'],
vsep: ' ',
})
.split('\n')
.join(`\n${spacer}`));
}
function targetToRow(target) {
var _a, _b, _c, _d;
return [
(_c = (_b = (_a = target.name) !== null && _a !== void 0 ? _a : target.model) !== null && _b !== void 0 ? _b : target.id) !== null && _c !== void 0 ? _c : '?',
`${target.platform === 'ios' ? 'iOS' : 'API'} ${target.sdkVersion}`,
(_d = target.id) !== null && _d !== void 0 ? _d : '?',
];
}

@@ -16,3 +16,8 @@ "use strict";

exports.onBeforeExit = onBeforeExit;
const BEFORE_EXIT_SIGNALS = ['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGBREAK'];
const BEFORE_EXIT_SIGNALS = [
'SIGINT',
'SIGTERM',
'SIGHUP',
'SIGBREAK',
];
const beforeExitHandlerWrapper = (signal) => fn_1.once(async () => {

@@ -19,0 +24,0 @@ debug('onBeforeExit handler: %s received', signal);

@@ -7,6 +7,7 @@ "use strict";

const yauzl = await Promise.resolve().then(() => require('yauzl'));
const open = util_1.promisify(yauzl.open.bind(yauzl));
return new Promise(async (resolve, reject) => {
try {
const zipfile = await open(srcPath, { lazyEntries: true });
return new Promise((resolve, reject) => {
yauzl.open(srcPath, { lazyEntries: true }, (err, zipfile) => {
if (!zipfile || err) {
return reject(err);
}
const openReadStream = util_1.promisify(zipfile.openReadStream.bind(zipfile));

@@ -19,8 +20,5 @@ zipfile.once('error', reject);

zipfile.readEntry();
}
catch (error) {
reject(error);
}
});
});
}
exports.unzip = unzip;
{
"name": "native-run",
"version": "1.1.0",
"version": "1.2.0",
"description": "A CLI for running apps on iOS/Android devices and simulators/emulators",

@@ -13,3 +13,6 @@ "bin": {

"test": "jest --maxWorkers=4",
"lint": "true",
"lint": "npm run eslint && npm run prettier -- --check",
"fmt": "npm run eslint -- --fix && npm run prettier -- --write",
"prettier": "prettier \"**/*.ts\"",
"eslint": "eslint . --ext .ts",
"publish:ci": "semantic-release",

@@ -39,2 +42,3 @@ "publish:testing": "npm version prerelease --preid=testing --no-git-tag-version && npm publish --tag=testing && git stash",

"@ionic/utils-fs": "^3.0.0",
"@ionic/utils-terminal": "^2.3.0",
"bplist-parser": "0.2.0",

@@ -51,2 +55,4 @@ "debug": "^4.1.1",

"devDependencies": {
"@ionic/eslint-config": "^0.3.0",
"@ionic/prettier-config": "^1.0.1",
"@semantic-release/changelog": "^5.0.0",

@@ -61,7 +67,10 @@ "@semantic-release/git": "^9.0.0",

"@types/plist": "^3.0.2",
"@types/slice-ansi": "^4.0.0",
"@types/split2": "^2.1.6",
"@types/through2": "^2.0.34",
"@types/yauzl": "^2.9.1",
"eslint": "^7.8.1",
"husky": "^4.0.9",
"jest": "^26.4.2",
"prettier": "^2.1.1",
"semantic-release": "^17.1.1",

@@ -71,2 +80,14 @@ "ts-jest": "^26.3.0",

},
"prettier": "@ionic/prettier-config",
"eslintConfig": {
"extends": "@ionic/eslint-config/recommended",
"rules": {
"@typescript-eslint/explicit-module-boundary-types": [
"warn",
{
"allowArgumentsExplicitlyTypedAsAny": true
}
]
}
},
"release": {

@@ -73,0 +94,0 @@ "branches": "stable",

@@ -1,8 +0,8 @@

[![Build Status](https://circleci.com/gh/ionic-team/native-run.svg?style=shield)](https://circleci.com/gh/ionic-team/native-run)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
[![npm](https://img.shields.io/npm/v/native-run.svg)](https://www.npmjs.com/package/native-run)
[![github-actions](https://img.shields.io/github/workflow/status/ionic-team/native-run/CI/develop?style=flat-square)](https://github.com/ionic-team/native-run/actions?query=workflow%3ACI)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)](https://github.com/semantic-release/semantic-release)
[![npm](https://img.shields.io/npm/v/native-run.svg?style=flat-square)](https://www.npmjs.com/package/native-run)
# native-run
`native-run` is a cross-platform command-line utility for running native binaries on devices and simulators/emulators. It supports deploying both `.apk` and `.ipa` files to Android and iOS devices.
`native-run` is a cross-platform command-line utility for running native app binaries (`.ipa` and `.apk` files) on iOS and Android devices. It can be used for both hardware and virtual devices.

@@ -13,20 +13,28 @@ This tool is used by the Ionic CLI, but it can be used standalone as part of a development or testing pipeline for launching apps. It doesn't matter whether the `.apk` or `.ipa` is created with Cordova or native IDEs, `native-run` will be able to deploy it.

`native-run` is written entirely in TypeScript/NodeJS and it has no native dependencies. It requires NodeJS 10 or later. To install, run:
`native-run` is written entirely in TypeScript/NodeJS, so there are no native dependencies.
```console
$ npm install -g native-run
To install, run:
```
npm install -g native-run
```
:memo: Requires NodeJS 10+
## Usage
```console
$ native-run <platform> [options]
```
native-run <platform> [options]
```
See the help documentation with the `--help` flag.
```console
$ native-run --help
$ native-run ios --help
$ native-run android --help
```
native-run --help
native-run ios --help
native-run android --help
```
### Troubleshooting
Much more information can be printed to the screen with the `--verbose` flag.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc