Add capacitorjs runtime

This commit is contained in:
olcxja 2026-05-03 17:09:55 +02:00
commit f90c0e6c40
8362 changed files with 1502407 additions and 1 deletions

21
node_modules/native-run/LICENSE generated vendored Normal file
View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2018 Drifty Co
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

39
node_modules/native-run/README.md generated vendored Normal file
View file

@ -0,0 +1,39 @@
[![github-actions](https://img.shields.io/github/actions/workflow/status/ionic-team/native-run/ci.yml?branch=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 app binaries (`.ipa` and `.apk` files) on iOS and Android devices. It can be used for both hardware and virtual devices.
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.
## Install
`native-run` is written entirely in TypeScript/NodeJS, so there are no native dependencies.
To install, run:
```
npm install -g native-run
```
:memo: Requires NodeJS 16+
## Usage
```
native-run <platform> [options]
```
See the help documentation with the `--help` flag.
```
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.

10
node_modules/native-run/assets/android/skins/LICENSE generated vendored Normal file
View file

@ -0,0 +1,10 @@
Copyright (C) 2013 The Android Open Source Project Licensed under the Apache
License, Version 2.0 (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

View file

@ -0,0 +1,4 @@
# Android Skins
These skins are copied from the Android Plugin for IntelliJ IDEA:
https://github.com/JetBrains/android/tree/master/artwork/resources/device-art-resources

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,59 @@
parts {
device {
display {
width 1080
height 1920
x 0
y 0
}
}
portrait {
background {
image port_back.webp
}
onion {
image port_fore.webp
}
}
landscape {
background {
image land_back.webp
}
onion {
image land_fore.webp
}
}
}
layouts {
portrait {
width 1370
height 2446
event EV_SW:0:1
part1 {
name portrait
x 0
y 0
}
part2 {
name device
x 147
y 233
}
}
landscape {
width 2497
height 1234
event EV_SW:0:0
part1 {
name landscape
x 0
y 0
}
part2 {
name device
x 278
y 1143
rotation 3
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -0,0 +1,59 @@
parts {
device {
display {
width 1080
height 1920
x 0
y 0
}
}
portrait {
background {
image port_back.webp
}
onion {
image port_fore.webp
}
}
landscape {
background {
image land_back.webp
}
onion {
image land_fore.webp
}
}
}
layouts {
portrait {
width 1370
height 2534
event EV_SW:0:1
part1 {
name portrait
x 0
y 0
}
part2 {
name device
x 139
y 285
}
}
landscape {
width 2596
height 1258
event EV_SW:0:0
part1 {
name landscape
x 0
y 0
}
part2 {
name device
x 338
y 1158
rotation 3
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -0,0 +1,59 @@
parts {
device {
display {
width 1080
height 1920
x 0
y 0
}
}
portrait {
background {
image port_back.webp
}
onion {
image port_fore.webp
}
}
landscape {
background {
image land_back.webp
}
onion {
image land_fore.webp
}
}
}
layouts {
portrait {
width 1370
height 2534
event EV_SW:0:1
part1 {
name portrait
x 0
y 0
}
part2 {
name device
x 140
y 280
}
}
landscape {
width 2596
height 1258
event EV_SW:0:0
part1 {
name landscape
x 0
y 0
}
part2 {
name device
x 338
y 68
rotation 3
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -0,0 +1,38 @@
parts {
device {
display {
width 1080
height 2160
x 0
y 0
}
}
portrait {
background {
image port_back.webp
}
foreground {
mask round_corners.webp
}
onion {
image port_fore.webp
}
}
}
layouts {
portrait {
width 1194
height 2532
event EV_SW:0:1
part1 {
name portrait
x 0
y 0
}
part2 {
name device
x 54
y 196
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

11
node_modules/native-run/bin/native-run generated vendored Executable file
View file

@ -0,0 +1,11 @@
#!/usr/bin/env node
'use strict';
process.title = 'native-run';
if (process.argv.includes('--verbose')) {
process.env.DEBUG = '*';
}
require('../').run();

38
node_modules/native-run/dist/android/help.js generated vendored Normal file
View file

@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = void 0;
const help = `
Usage: native-run android [options]
Run an .apk on a device or emulator target
Targets are selected as follows:
1) --target using device/emulator serial number or AVD ID
2) A connected device, unless --virtual is used
3) A running emulator
If the above criteria are not met, an emulator is started from a default
AVD, which is created if it does not exist.
Use --list to list available targets.
Options:
--list .................. Print available targets, then quit
--sdk-info .............. Print SDK information, then quit
--json .................. Output JSON
--app <path> ............ Deploy specified .apk file
--device ................ Use a device if available
With --list prints connected devices
--virtual ............... Prefer an emulator
With --list prints available emulators
--target <id> ........... Use a specific target
--connect ............... Tie process to app process
--forward <port:port> ... Forward a port from device to host
`;
async function run(args) {
process.stdout.write(`${help}\n`);
}
exports.run = run;

21
node_modules/native-run/dist/android/index.js generated vendored Normal file
View file

@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = void 0;
async function run(args) {
let cmd;
if (args.includes('--help') || args.includes('-h')) {
cmd = await Promise.resolve().then(() => require('./help'));
return cmd.run(args);
}
if (args.includes('--list')) {
cmd = await Promise.resolve().then(() => require('./list'));
return cmd.run(args);
}
if (args.includes('--sdk-info')) {
cmd = await Promise.resolve().then(() => require('./sdk-info'));
return cmd.run(args);
}
cmd = await Promise.resolve().then(() => require('./run'));
await cmd.run(args);
}
exports.run = run;

37
node_modules/native-run/dist/android/list.js generated vendored Normal file
View file

@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.list = exports.run = void 0;
const list_1 = require("../utils/list");
const list_2 = require("./utils/list");
const sdk_1 = require("./utils/sdk");
async function run(args) {
const targets = await list(args);
process.stdout.write(`\n${(0, list_1.formatTargets)(args, targets)}\n`);
}
exports.run = run;
async function list(args) {
const sdk = await (0, sdk_1.getSDK)();
const errors = [];
const [devices, virtualDevices] = await Promise.all([
(async () => {
try {
return await (0, list_2.getDeviceTargets)(sdk);
}
catch (e) {
errors.push(e);
return [];
}
})(),
(async () => {
try {
return await (0, list_2.getVirtualTargets)(sdk);
}
catch (e) {
errors.push(e);
return [];
}
})(),
]);
return { devices, virtualDevices, errors };
}
exports.list = list;

103
node_modules/native-run/dist/android/run.js generated vendored Normal file
View file

@ -0,0 +1,103 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.selectDevice = exports.run = void 0;
const Debug = require("debug");
const errors_1 = require("../errors");
const cli_1 = require("../utils/cli");
const log_1 = require("../utils/log");
const process_1 = require("../utils/process");
const adb_1 = require("./utils/adb");
const apk_1 = require("./utils/apk");
const avd_1 = require("./utils/avd");
const run_1 = require("./utils/run");
const sdk_1 = require("./utils/sdk");
const modulePrefix = 'native-run:android:run';
async function run(args) {
const sdk = await (0, sdk_1.getSDK)();
const apkPath = (0, cli_1.getOptionValue)(args, '--app');
const forwardedPorts = (0, cli_1.getOptionValues)(args, '--forward');
const ports = [];
if (forwardedPorts && forwardedPorts.length > 0) {
forwardedPorts.forEach((port) => {
const [device, host] = port.split(':');
if (!device || !host) {
throw new errors_1.CLIException(`Invalid --forward value "${port}": expecting <device port:host port>, e.g. 8080:8080`);
}
ports.push({ device, host });
});
}
if (!apkPath) {
throw new errors_1.CLIException('--app is required', errors_1.ERR_BAD_INPUT);
}
const device = await selectDevice(sdk, args);
(0, log_1.log)(`Selected ${device.type === 'hardware' ? 'hardware device' : 'emulator'} ${device.serial}\n`);
const { appId, activityName } = await (0, apk_1.getApkInfo)(apkPath);
await (0, adb_1.waitForBoot)(sdk, device);
if (ports) {
await Promise.all(ports.map(async (port) => {
await (0, adb_1.forwardPorts)(sdk, device, port);
(0, log_1.log)(`Forwarded device port ${port.device} to host port ${port.host}\n`);
}));
}
await (0, run_1.installApkToDevice)(sdk, device, apkPath, appId);
(0, log_1.log)(`Starting application activity ${appId}/${activityName}...\n`);
await (0, adb_1.startActivity)(sdk, device, appId, activityName);
(0, log_1.log)(`Run Successful\n`);
(0, process_1.onBeforeExit)(async () => {
if (ports) {
await Promise.all(ports.map(async (port) => {
await (0, adb_1.unforwardPorts)(sdk, device, port);
}));
}
});
if (args.includes('--connect')) {
(0, process_1.onBeforeExit)(async () => {
await (0, adb_1.closeApp)(sdk, device, appId);
});
(0, log_1.log)(`Waiting for app to close...\n`);
await (0, adb_1.waitForClose)(sdk, device, appId);
}
}
exports.run = run;
async function selectDevice(sdk, args) {
const debug = Debug(`${modulePrefix}:${selectDevice.name}`);
const devices = await (0, adb_1.getDevices)(sdk);
const avds = await (0, avd_1.getInstalledAVDs)(sdk);
const target = (0, cli_1.getOptionValue)(args, '--target');
const preferEmulator = args.includes('--virtual');
if (target) {
const targetDevice = await (0, run_1.selectDeviceByTarget)(sdk, devices, avds, target);
if (targetDevice) {
return targetDevice;
}
else {
throw new errors_1.AndroidRunException(`Target not found: ${target}`, errors_1.ERR_TARGET_NOT_FOUND);
}
}
if (!preferEmulator) {
const selectedDevice = await (0, run_1.selectHardwareDevice)(devices);
if (selectedDevice) {
return selectedDevice;
}
else if (args.includes('--device')) {
throw new errors_1.AndroidRunException(`No hardware devices found. Not attempting emulator because --device was specified.`, errors_1.ERR_NO_DEVICE);
}
else {
(0, log_1.log)('No hardware devices found, attempting emulator...\n');
}
}
try {
return await (0, run_1.selectVirtualDevice)(sdk, devices, avds);
}
catch (e) {
if (!(e instanceof errors_1.AVDException)) {
throw e;
}
debug('Issue with AVDs: %s', e.message);
if (e.code === errors_1.ERR_UNSUITABLE_API_INSTALLATION) {
throw new errors_1.AndroidRunException('No targets devices/emulators available. Cannot create AVD because there is no suitable API installation. Use --sdk-info to reveal missing packages and other issues.', errors_1.ERR_NO_TARGET);
}
}
throw new errors_1.AndroidRunException('No target devices/emulators available.', errors_1.ERR_NO_TARGET);
}
exports.selectDevice = selectDevice;

46
node_modules/native-run/dist/android/sdk-info.js generated vendored Normal file
View file

@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = void 0;
const json_1 = require("../utils/json");
const sdk_1 = require("./utils/sdk");
const api_1 = require("./utils/sdk/api");
async function run(args) {
const sdk = await (0, sdk_1.getSDK)();
const packages = await (0, sdk_1.findAllSDKPackages)(sdk);
const apis = await (0, api_1.getAPILevels)(packages);
const platforms = apis.map((api) => {
return { ...api };
});
const sdkinfo = {
root: sdk.root,
avdHome: sdk.avdHome,
platforms,
tools: packages.filter((pkg) => typeof pkg.apiLevel === 'undefined'),
};
if (args.includes('--json')) {
process.stdout.write((0, json_1.stringify)(sdkinfo));
return;
}
process.stdout.write(`${formatSDKInfo(sdkinfo)}\n\n`);
}
exports.run = run;
function formatSDKInfo(sdk) {
return `
SDK Location: ${sdk.root}
AVD Home${sdk.avdHome ? `: ${sdk.avdHome}` : ` (!): not found`}
${sdk.platforms.map((platform) => `${formatPlatform(platform)}\n\n`).join('\n')}
Tools:
${sdk.tools.map((tool) => formatPackage(tool)).join('\n')}
`.trim();
}
function formatPlatform(platform) {
return `
API Level: ${platform.apiLevel}
Packages: ${platform.packages.map((p) => formatPackage(p)).join('\n' + ' '.repeat(22))}
`.trim();
}
function formatPackage(p) {
return `${p.name} ${p.path} ${typeof p.version === 'string' ? p.version : ''}`;
}

318
node_modules/native-run/dist/android/utils/adb.js generated vendored Normal file
View file

@ -0,0 +1,318 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
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");
const Debug = require("debug");
const os = require("os");
const path = require("path");
const split2 = require("split2");
const through2 = require("through2");
const errors_1 = require("../../errors");
const process_1 = require("../../utils/process");
const sdk_1 = require("./sdk");
const modulePrefix = 'native-run:android:utils:adb';
const ADB_GETPROP_MAP = new Map([
['ro.product.manufacturer', 'manufacturer'],
['ro.product.model', 'model'],
['ro.product.name', 'product'],
['ro.build.version.sdk', 'sdkVersion'],
]);
async function getDevices(sdk) {
const debug = Debug(`${modulePrefix}:${getDevices.name}`);
const args = ['devices', '-l'];
debug('Invoking adb with args: %O', args);
const stdout = await execAdb(sdk, args, { timeout: 5000 });
const devices = parseAdbDevices(stdout);
await Promise.all(devices.map(async (device) => {
const properties = await getDeviceProperties(sdk, device);
for (const [prop, deviceProp] of ADB_GETPROP_MAP.entries()) {
const value = properties[prop];
if (value) {
device[deviceProp] = value;
}
}
}));
debug('Found adb devices: %O', devices);
return devices;
}
exports.getDevices = getDevices;
async function getDeviceProperty(sdk, device, property) {
const debug = Debug(`${modulePrefix}:${getDeviceProperty.name}`);
const args = ['-s', device.serial, 'shell', 'getprop', property];
debug('Invoking adb with args: %O', args);
const stdout = await execAdb(sdk, args, { timeout: 5000 });
return stdout.trim();
}
exports.getDeviceProperty = getDeviceProperty;
async function getDeviceProperties(sdk, device) {
const debug = Debug(`${modulePrefix}:${getDeviceProperties.name}`);
const args = ['-s', device.serial, 'shell', 'getprop'];
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 properties = {};
for (const line of stdout.split(os.EOL)) {
const m = line.match(re);
if (m) {
const [, key, value] = m;
if (propAllowList.includes(key)) {
properties[key] = value;
}
}
}
return properties;
}
exports.getDeviceProperties = getDeviceProperties;
async function waitForDevice(sdk, serial) {
const debug = Debug(`${modulePrefix}:${waitForDevice.name}`);
const args = ['-s', serial, 'wait-for-any-device'];
debug('Invoking adb with args: %O', args);
await execAdb(sdk, args);
debug('Device %s is connected to ADB!', serial);
}
exports.waitForDevice = waitForDevice;
async function waitForBoot(sdk, device) {
const debug = Debug(`${modulePrefix}:${waitForBoot.name}`);
return new Promise((resolve) => {
const interval = setInterval(async () => {
const booted = await getDeviceProperty(sdk, device, 'dev.bootcomplete');
if (booted) {
debug('Device %s is booted!', device.serial);
clearInterval(interval);
resolve();
}
}, 100);
});
}
exports.waitForBoot = waitForBoot;
async function waitForClose(sdk, device, app) {
const debug = Debug(`${modulePrefix}:${waitForClose.name}`);
const args = ['-s', device.serial, 'shell', `ps | grep ${app}`];
return new Promise((resolve) => {
const interval = setInterval(async () => {
try {
debug('Invoking adb with args: %O', args);
await execAdb(sdk, args);
}
catch (e) {
debug('Error received from adb: %O', e);
debug('App %s no longer found in process list for %s', app, device.serial);
clearInterval(interval);
resolve();
}
}, 500);
});
}
exports.waitForClose = waitForClose;
async function installApk(sdk, device, apk) {
const debug = Debug(`${modulePrefix}:${installApk.name}`);
const platformTools = await (0, sdk_1.getSDKPackage)(path.join(sdk.root, 'platform-tools'));
const adbBin = path.join(platformTools.location, 'adb');
const args = ['-s', device.serial, 'install', '-r', '-t', apk];
debug('Invoking adb with args: %O', args);
const p = (0, child_process_1.spawn)(adbBin, args, {
stdio: 'pipe',
env: (0, sdk_1.supplementProcessEnv)(sdk),
});
return new Promise((resolve, reject) => {
p.on('close', (code) => {
if (code === 0) {
resolve();
}
else {
reject(new errors_1.ADBException(`Non-zero exit code from adb: ${code}`));
}
});
p.on('error', (err) => {
debug('adb install error: %O', err);
reject(err);
});
p.stderr.pipe(split2()).pipe(through2((chunk, enc, cb) => {
const line = chunk.toString();
debug('adb install: %O', line);
const event = parseAdbInstallOutput(line);
if (event === ADBEvent.IncompatibleUpdateFailure) {
reject(new errors_1.ADBException(`Encountered adb error: ${ADBEvent[event]}.`, errors_1.ERR_INCOMPATIBLE_UPDATE));
}
else if (event === ADBEvent.NewerVersionOnDeviceFailure) {
reject(new errors_1.ADBException(`Encountered adb error: ${ADBEvent[event]}.`, errors_1.ERR_VERSION_DOWNGRADE));
}
else if (event === ADBEvent.NewerSdkRequiredOnDeviceFailure) {
reject(new errors_1.ADBException(`Encountered adb error: ${ADBEvent[event]}.`, errors_1.ERR_MIN_SDK_VERSION));
}
else if (event === ADBEvent.NoCertificates) {
reject(new errors_1.ADBException(`Encountered adb error: ${ADBEvent[event]}.`, errors_1.ERR_NO_CERTIFICATES));
}
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();
}));
});
}
exports.installApk = installApk;
async function closeApp(sdk, device, app) {
const debug = Debug(`${modulePrefix}:${closeApp.name}`);
const args = ['-s', device.serial, 'shell', 'am', 'force-stop', app];
debug('Invoking adb with args: %O', args);
await execAdb(sdk, args);
}
exports.closeApp = closeApp;
async function uninstallApp(sdk, device, app) {
const debug = Debug(`${modulePrefix}:${uninstallApp.name}`);
const args = ['-s', device.serial, 'uninstall', app];
debug('Invoking adb with args: %O', args);
await execAdb(sdk, args);
}
exports.uninstallApp = uninstallApp;
var ADBEvent;
(function (ADBEvent) {
ADBEvent[ADBEvent["IncompatibleUpdateFailure"] = 0] = "IncompatibleUpdateFailure";
ADBEvent[ADBEvent["NewerVersionOnDeviceFailure"] = 1] = "NewerVersionOnDeviceFailure";
ADBEvent[ADBEvent["NewerSdkRequiredOnDeviceFailure"] = 2] = "NewerSdkRequiredOnDeviceFailure";
ADBEvent[ADBEvent["NoCertificates"] = 3] = "NoCertificates";
ADBEvent[ADBEvent["NotEnoughSpace"] = 4] = "NotEnoughSpace";
ADBEvent[ADBEvent["DeviceOffline"] = 5] = "DeviceOffline";
})(ADBEvent = exports.ADBEvent || (exports.ADBEvent = {}));
function parseAdbInstallOutput(line) {
const debug = Debug(`${modulePrefix}:${parseAdbInstallOutput.name}`);
let event;
if (line.includes('INSTALL_FAILED_UPDATE_INCOMPATIBLE')) {
event = ADBEvent.IncompatibleUpdateFailure;
}
else if (line.includes('INSTALL_FAILED_VERSION_DOWNGRADE')) {
event = ADBEvent.NewerVersionOnDeviceFailure;
}
else if (line.includes('INSTALL_FAILED_OLDER_SDK')) {
event = ADBEvent.NewerSdkRequiredOnDeviceFailure;
}
else if (line.includes('INSTALL_PARSE_FAILED_NO_CERTIFICATES')) {
event = ADBEvent.NoCertificates;
}
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') {
debug('Parsed event from adb install output: %s', ADBEvent[event]);
}
return event;
}
exports.parseAdbInstallOutput = parseAdbInstallOutput;
async function startActivity(sdk, device, packageName, activityName) {
const debug = Debug(`${modulePrefix}:${startActivity.name}`);
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 });
}
exports.startActivity = startActivity;
function parseAdbDevices(output) {
const debug = Debug(`${modulePrefix}:${parseAdbDevices.name}`);
const re = /^([\S]+)\s+([a-z\s]+)\s+(.*)$/;
const ipRe = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+$/;
const lines = output.split(os.EOL);
debug('Parsing adb devices from output lines: %O', lines);
const devices = [];
for (const line of lines) {
if (line && !line.startsWith('List')) {
const m = line.match(re);
if (m) {
const [, serial, state, description] = m;
const properties = description
.split(/\s+/)
.map((prop) => (prop.includes(':') ? prop.split(':') : undefined))
.filter((kv) => typeof kv !== 'undefined' && kv.length >= 2)
.reduce((acc, [k, v]) => {
if (k && v) {
acc[k.trim()] = v.trim();
}
return acc;
}, {});
const isIP = !!serial.match(ipRe);
const isGenericDevice = (properties['device'] || '').startsWith('generic');
const type = 'usb' in properties || isIP || !serial.startsWith('emulator') || !isGenericDevice ? 'hardware' : 'emulator';
const connection = 'usb' in properties ? 'usb' : isIP ? 'tcpip' : null;
devices.push({
serial,
state,
type,
connection,
properties,
// We might not know these yet
manufacturer: '',
model: properties['model'] || '',
product: properties['product'] || '',
sdkVersion: '',
});
}
else {
debug('adb devices output line does not match expected regex: %O', line);
}
}
}
return devices;
}
exports.parseAdbDevices = parseAdbDevices;
async function forwardPorts(sdk, device, ports) {
const debug = Debug(`${modulePrefix}:${forwardPorts.name}`);
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}:${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 () => {
const msg = `ADBs is unresponsive after ${options.timeout}ms, killing server and retrying...\n`;
if (process.argv.includes('--json')) {
debug(msg);
}
else {
process.stderr.write(msg);
}
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 (0, sdk_1.getSDKPackage)(path.join(sdk.root, 'platform-tools'));
const adbBin = path.join(platformTools.location, 'adb');
const { stdout } = await (0, process_1.execFile)(adbBin, args, {
env: (0, 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;

36
node_modules/native-run/dist/android/utils/apk.js generated vendored Normal file
View file

@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getApkInfo = exports.readAndroidManifest = void 0;
const unzip_1 = require("../../utils/unzip");
const binary_xml_parser_1 = require("./binary-xml-parser");
async function readAndroidManifest(apkPath) {
let error;
const chunks = [];
await (0, unzip_1.unzip)(apkPath, async (entry, zipfile, openReadStream) => {
if (entry.fileName === 'AndroidManifest.xml') {
const readStream = await openReadStream(entry);
readStream.on('error', (err) => (error = err));
readStream.on('data', (chunk) => chunks.push(chunk));
readStream.on('end', () => zipfile.close());
}
else {
zipfile.readEntry();
}
});
if (error) {
throw error;
}
const buf = Buffer.concat(chunks);
const manifestBuffer = Buffer.from(buf);
return new binary_xml_parser_1.BinaryXmlParser(manifestBuffer).parse();
}
exports.readAndroidManifest = readAndroidManifest;
async function getApkInfo(apkPath) {
const doc = await readAndroidManifest(apkPath);
const appId = doc.attributes.find((a) => a.name === 'package').value;
const application = doc.childNodes.find((n) => n.nodeName === 'application');
const activity = application.childNodes.find((n) => n.nodeName === 'activity');
const activityName = activity.attributes.find((a) => a.name === 'name').value;
return { appId, activityName };
}
exports.getApkInfo = getApkInfo;

69
node_modules/native-run/dist/android/utils/avd.js generated vendored Normal file
View file

@ -0,0 +1,69 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getInstalledAVDs = exports.getAVDFromINI = exports.getSDKVersionFromTarget = exports.getAVDFromConfigINI = exports.getAVDINIs = exports.isAVDConfigINI = exports.isAVDINI = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const Debug = require("debug");
const pathlib = require("path");
const ini_1 = require("../../utils/ini");
const modulePrefix = 'native-run:android:utils:avd';
const isAVDINI = (o) => o &&
typeof o['avd.ini.encoding'] === 'string' &&
typeof o['path'] === 'string' &&
typeof o['path.rel'] === 'string' &&
typeof o['target'] === 'string';
exports.isAVDINI = isAVDINI;
const 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.isAVDConfigINI = isAVDConfigINI;
async function getAVDINIs(sdk) {
const debug = Debug(`${modulePrefix}:${getAVDINIs.name}`);
const contents = await (0, utils_fs_1.readdir)(sdk.avdHome);
const iniFilePaths = contents
.filter((f) => pathlib.extname(f) === '.ini')
.map((f) => pathlib.resolve(sdk.avdHome, f));
debug('Discovered AVD ini files: %O', iniFilePaths);
const iniFiles = await Promise.all(iniFilePaths.map(async (f) => [f, await (0, ini_1.readINI)(f, exports.isAVDINI)]));
const avdInis = iniFiles.filter((c) => typeof c[1] !== 'undefined');
return avdInis;
}
exports.getAVDINIs = getAVDINIs;
function getAVDFromConfigINI(inipath, ini, configini) {
const inibasename = pathlib.basename(inipath);
const id = inibasename.substring(0, inibasename.length - pathlib.extname(inibasename).length);
const name = configini['avd.ini.displayname'] ? String(configini['avd.ini.displayname']) : 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;
return {
id,
path: ini.path,
name,
sdkVersion: getSDKVersionFromTarget(ini.target),
screenDPI,
screenWidth,
screenHeight,
};
}
exports.getAVDFromConfigINI = getAVDFromConfigINI;
function getSDKVersionFromTarget(target) {
return target.replace(/^android-(\d+)/, '$1');
}
exports.getSDKVersionFromTarget = getSDKVersionFromTarget;
async function getAVDFromINI(inipath, ini) {
const configini = await (0, ini_1.readINI)(pathlib.resolve(ini.path, 'config.ini'), exports.isAVDConfigINI);
if (configini) {
return getAVDFromConfigINI(inipath, ini, configini);
}
}
exports.getAVDFromINI = getAVDFromINI;
async function getInstalledAVDs(sdk) {
const avdInis = await getAVDINIs(sdk);
const possibleAvds = await Promise.all(avdInis.map(([inipath, ini]) => getAVDFromINI(inipath, ini)));
const avds = possibleAvds.filter((avd) => typeof avd !== 'undefined');
return avds;
}
exports.getInstalledAVDs = getInstalledAVDs;

View file

@ -0,0 +1,593 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BinaryXmlParser = void 0;
/*
Copyright © 2013 CyberAgent, Inc.
Copyright © 2016 The OpenSTF Project
Modifications Copyright © 2018 Drifty Co
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
https://github.com/openstf/adbkit-apkreader/blob/368f6b207c57e82fa7373c1608920ca7f4a8904c/lib/apkreader/parser/binaryxml.js
*/
const assert = require("assert");
// import * as Debug from 'debug';
const errors_1 = require("../../errors");
// const debug = Debug('native-run:android:util:binary-xml-parser');
const NodeType = {
ELEMENT_NODE: 1,
ATTRIBUTE_NODE: 2,
CDATA_SECTION_NODE: 4,
};
const ChunkType = {
NULL: 0x0000,
STRING_POOL: 0x0001,
TABLE: 0x0002,
XML: 0x0003,
XML_FIRST_CHUNK: 0x0100,
XML_START_NAMESPACE: 0x0100,
XML_END_NAMESPACE: 0x0101,
XML_START_ELEMENT: 0x0102,
XML_END_ELEMENT: 0x0103,
XML_CDATA: 0x0104,
XML_LAST_CHUNK: 0x017f,
XML_RESOURCE_MAP: 0x0180,
TABLE_PACKAGE: 0x0200,
TABLE_TYPE: 0x0201,
TABLE_TYPE_SPEC: 0x0202,
};
const StringFlags = {
SORTED: 1 << 0,
UTF8: 1 << 8,
};
// Taken from android.util.TypedValue
const TypedValue = {
COMPLEX_MANTISSA_MASK: 0x00ffffff,
COMPLEX_MANTISSA_SHIFT: 0x00000008,
COMPLEX_RADIX_0p23: 0x00000003,
COMPLEX_RADIX_16p7: 0x00000001,
COMPLEX_RADIX_23p0: 0x00000000,
COMPLEX_RADIX_8p15: 0x00000002,
COMPLEX_RADIX_MASK: 0x00000003,
COMPLEX_RADIX_SHIFT: 0x00000004,
COMPLEX_UNIT_DIP: 0x00000001,
COMPLEX_UNIT_FRACTION: 0x00000000,
COMPLEX_UNIT_FRACTION_PARENT: 0x00000001,
COMPLEX_UNIT_IN: 0x00000004,
COMPLEX_UNIT_MASK: 0x0000000f,
COMPLEX_UNIT_MM: 0x00000005,
COMPLEX_UNIT_PT: 0x00000003,
COMPLEX_UNIT_PX: 0x00000000,
COMPLEX_UNIT_SHIFT: 0x00000000,
COMPLEX_UNIT_SP: 0x00000002,
DENSITY_DEFAULT: 0x00000000,
DENSITY_NONE: 0x0000ffff,
TYPE_ATTRIBUTE: 0x00000002,
TYPE_DIMENSION: 0x00000005,
TYPE_FIRST_COLOR_INT: 0x0000001c,
TYPE_FIRST_INT: 0x00000010,
TYPE_FLOAT: 0x00000004,
TYPE_FRACTION: 0x00000006,
TYPE_INT_BOOLEAN: 0x00000012,
TYPE_INT_COLOR_ARGB4: 0x0000001e,
TYPE_INT_COLOR_ARGB8: 0x0000001c,
TYPE_INT_COLOR_RGB4: 0x0000001f,
TYPE_INT_COLOR_RGB8: 0x0000001d,
TYPE_INT_DEC: 0x00000010,
TYPE_INT_HEX: 0x00000011,
TYPE_LAST_COLOR_INT: 0x0000001f,
TYPE_LAST_INT: 0x0000001f,
TYPE_NULL: 0x00000000,
TYPE_REFERENCE: 0x00000001,
TYPE_STRING: 0x00000003,
};
class BinaryXmlParser {
constructor(buffer, options = {}) {
this.buffer = buffer;
this.cursor = 0;
this.strings = [];
this.resources = [];
this.stack = [];
this.debug = false;
this.debug = options.debug || false;
}
readU8() {
// debug('readU8');
// debug('cursor:', this.cursor);
const val = this.buffer[this.cursor];
// debug('value:', val);
this.cursor += 1;
return val;
}
readU16() {
// debug('readU16');
// debug('cursor:', this.cursor);
const val = this.buffer.readUInt16LE(this.cursor);
// debug('value:', val);
this.cursor += 2;
return val;
}
readS32() {
// debug('readS32');
// debug('cursor:', this.cursor);
const val = this.buffer.readInt32LE(this.cursor);
// debug('value:', val);
this.cursor += 4;
return val;
}
readU32() {
// debug('readU32');
// debug('cursor:', this.cursor);
const val = this.buffer.readUInt32LE(this.cursor);
// debug('value:', val);
this.cursor += 4;
return val;
}
readLength8() {
// debug('readLength8');
let len = this.readU8();
if (len & 0x80) {
len = (len & 0x7f) << 8;
len += this.readU8();
}
// debug('length:', len);
return len;
}
readLength16() {
// debug('readLength16');
let len = this.readU16();
if (len & 0x8000) {
len = (len & 0x7fff) << 16;
len += this.readU16();
}
// debug('length:', len);
return len;
}
readDimension() {
// debug('readDimension');
const dimension = {
value: null,
unit: null,
rawUnit: null,
};
const value = this.readU32();
const unit = dimension.value & 0xff;
dimension.value = value >> 8;
dimension.rawUnit = unit;
switch (unit) {
case TypedValue.COMPLEX_UNIT_MM:
dimension.unit = 'mm';
break;
case TypedValue.COMPLEX_UNIT_PX:
dimension.unit = 'px';
break;
case TypedValue.COMPLEX_UNIT_DIP:
dimension.unit = 'dp';
break;
case TypedValue.COMPLEX_UNIT_SP:
dimension.unit = 'sp';
break;
case TypedValue.COMPLEX_UNIT_PT:
dimension.unit = 'pt';
break;
case TypedValue.COMPLEX_UNIT_IN:
dimension.unit = 'in';
break;
}
return dimension;
}
readFraction() {
// debug('readFraction');
const fraction = {
value: null,
type: null,
rawType: null,
};
const value = this.readU32();
const type = value & 0xf;
fraction.value = this.convertIntToFloat(value >> 4);
fraction.rawType = type;
switch (type) {
case TypedValue.COMPLEX_UNIT_FRACTION:
fraction.type = '%';
break;
case TypedValue.COMPLEX_UNIT_FRACTION_PARENT:
fraction.type = '%p';
break;
}
return fraction;
}
readHex24() {
// debug('readHex24');
const val = (this.readU32() & 0xffffff).toString(16);
return val;
}
readHex32() {
// debug('readHex32');
const val = this.readU32().toString(16);
return val;
}
readTypedValue() {
// debug('readTypedValue');
const typedValue = {
value: null,
type: null,
rawType: null,
};
const start = this.cursor;
let size = this.readU16();
/* const zero = */ this.readU8();
const dataType = this.readU8();
// Yes, there has been a real world APK where the size is malformed.
if (size === 0) {
size = 8;
}
typedValue.rawType = dataType;
switch (dataType) {
case TypedValue.TYPE_INT_DEC:
typedValue.value = this.readS32();
typedValue.type = 'int_dec';
break;
case TypedValue.TYPE_INT_HEX:
typedValue.value = this.readS32();
typedValue.type = 'int_hex';
break;
case TypedValue.TYPE_STRING: {
const ref = this.readS32();
typedValue.value = ref > 0 ? this.strings[ref] : '';
typedValue.type = 'string';
break;
}
case TypedValue.TYPE_REFERENCE: {
const id = this.readU32();
typedValue.value = `resourceId:0x${id.toString(16)}`;
typedValue.type = 'reference';
break;
}
case TypedValue.TYPE_INT_BOOLEAN:
typedValue.value = this.readS32() !== 0;
typedValue.type = 'boolean';
break;
case TypedValue.TYPE_NULL:
this.readU32();
typedValue.value = null;
typedValue.type = 'null';
break;
case TypedValue.TYPE_INT_COLOR_RGB8:
typedValue.value = this.readHex24();
typedValue.type = 'rgb8';
break;
case TypedValue.TYPE_INT_COLOR_RGB4:
typedValue.value = this.readHex24();
typedValue.type = 'rgb4';
break;
case TypedValue.TYPE_INT_COLOR_ARGB8:
typedValue.value = this.readHex32();
typedValue.type = 'argb8';
break;
case TypedValue.TYPE_INT_COLOR_ARGB4:
typedValue.value = this.readHex32();
typedValue.type = 'argb4';
break;
case TypedValue.TYPE_DIMENSION:
typedValue.value = this.readDimension();
typedValue.type = 'dimension';
break;
case TypedValue.TYPE_FRACTION:
typedValue.value = this.readFraction();
typedValue.type = 'fraction';
break;
default: {
// const type = dataType.toString(16);
// debug(`Not sure what to do with typed value of type 0x${type}, falling back to reading an uint32.`);
typedValue.value = this.readU32();
typedValue.type = 'unknown';
}
}
// Ensure we consume the whole value
const end = start + size;
if (this.cursor !== end) {
// const type = dataType.toString(16);
// const diff = end - this.cursor;
// debug(`Cursor is off by ${diff} bytes at ${this.cursor} at supposed end \
// of typed value of type 0x${type}. The typed value started at offset ${start} \
// and is supposed to end at offset ${end}. Ignoring the rest of the value.`);
this.cursor = end;
}
return typedValue;
}
// https://twitter.com/kawasima/status/427730289201139712
convertIntToFloat(int) {
const buf = new ArrayBuffer(4);
new Int32Array(buf)[0] = int;
return new Float32Array(buf)[0];
}
readString(encoding) {
// debug('readString', encoding);
let stringLength;
let byteLength;
let value;
switch (encoding) {
case 'utf-8':
stringLength = this.readLength8();
// debug('stringLength:', stringLength);
byteLength = this.readLength8();
// debug('byteLength:', byteLength);
value = this.buffer.toString(encoding, this.cursor, (this.cursor += byteLength));
// debug('value:', value);
assert.equal(this.readU8(), 0, 'String must end with trailing zero');
return value;
case 'ucs2':
stringLength = this.readLength16();
// debug('stringLength:', stringLength);
byteLength = stringLength * 2;
// debug('byteLength:', byteLength);
value = this.buffer.toString(encoding, this.cursor, (this.cursor += byteLength));
// debug('value:', value);
assert.equal(this.readU16(), 0, 'String must end with trailing zero');
return value;
default:
throw new errors_1.Exception(`Unsupported encoding '${encoding}'`);
}
}
readChunkHeader() {
// debug('readChunkHeader');
const header = {
startOffset: this.cursor,
chunkType: this.readU16(),
headerSize: this.readU16(),
chunkSize: this.readU32(),
};
// debug('startOffset:', header.startOffset);
// debug('chunkType:', header.chunkType);
// debug('headerSize:', header.headerSize);
// debug('chunkSize:', header.chunkSize);
return header;
}
readStringPool(header) {
// debug('readStringPool');
header.stringCount = this.readU32();
// debug('stringCount:', header.stringCount);
header.styleCount = this.readU32();
// debug('styleCount:', header.styleCount);
header.flags = this.readU32();
// debug('flags:', header.flags);
header.stringsStart = this.readU32();
// debug('stringsStart:', header.stringsStart);
header.stylesStart = this.readU32();
// debug('stylesStart:', header.stylesStart);
if (header.chunkType !== ChunkType.STRING_POOL) {
throw new errors_1.Exception('Invalid string pool header');
}
const offsets = [];
for (let i = 0, l = header.stringCount; i < l; ++i) {
// debug('offset:', i);
offsets.push(this.readU32());
}
// const sorted = (header.flags & StringFlags.SORTED) === StringFlags.SORTED;
// debug('sorted:', sorted);
const encoding = (header.flags & StringFlags.UTF8) === StringFlags.UTF8 ? 'utf-8' : 'ucs2';
// debug('encoding:', encoding);
const stringsStart = header.startOffset + header.stringsStart;
this.cursor = stringsStart;
for (let i = 0, l = header.stringCount; i < l; ++i) {
// debug('string:', i);
// debug('offset:', offsets[i]);
this.cursor = stringsStart + offsets[i];
this.strings.push(this.readString(encoding));
}
// Skip styles
this.cursor = header.startOffset + header.chunkSize;
return null;
}
readResourceMap(header) {
// debug('readResourceMap');
const count = Math.floor((header.chunkSize - header.headerSize) / 4);
for (let i = 0; i < count; ++i) {
this.resources.push(this.readU32());
}
return null;
}
readXmlNamespaceStart( /* header */) {
// debug('readXmlNamespaceStart');
this.readU32();
this.readU32();
this.readU32();
this.readU32();
// const line = this.readU32();
// const commentRef = this.readU32();
// const prefixRef = this.readS32();
// const uriRef = this.readS32();
// We don't currently care about the values, but they could
// be accessed like so:
//
// namespaceURI.prefix = this.strings[prefixRef] // if prefixRef > 0
// namespaceURI.uri = this.strings[uriRef] // if uriRef > 0
return null;
}
readXmlNamespaceEnd( /* header */) {
// debug('readXmlNamespaceEnd');
this.readU32();
this.readU32();
this.readU32();
this.readU32();
// const line = this.readU32();
// const commentRef = this.readU32();
// const prefixRef = this.readS32();
// const uriRef = this.readS32();
// We don't currently care about the values, but they could
// be accessed like so:
//
// namespaceURI.prefix = this.strings[prefixRef] // if prefixRef > 0
// namespaceURI.uri = this.strings[uriRef] // if uriRef > 0
return null;
}
readXmlElementStart( /* header */) {
// debug('readXmlElementStart');
const node = {
namespaceURI: null,
nodeType: NodeType.ELEMENT_NODE,
nodeName: null,
attributes: [],
childNodes: [],
};
this.readU32();
this.readU32();
// const line = this.readU32();
// const commentRef = this.readU32();
const nsRef = this.readS32();
const nameRef = this.readS32();
if (nsRef > 0) {
node.namespaceURI = this.strings[nsRef];
}
node.nodeName = this.strings[nameRef];
this.readU16();
this.readU16();
// const attrStart = this.readU16();
// const attrSize = this.readU16();
const attrCount = this.readU16();
// const idIndex = this.readU16();
// const classIndex = this.readU16();
// const styleIndex = this.readU16();
this.readU16();
this.readU16();
this.readU16();
for (let i = 0; i < attrCount; ++i) {
node.attributes.push(this.readXmlAttribute());
}
if (this.document) {
this.parent.childNodes.push(node);
this.parent = node;
}
else {
this.document = this.parent = node;
}
this.stack.push(node);
return node;
}
readXmlAttribute() {
// debug('readXmlAttribute');
const attr = {
namespaceURI: null,
nodeType: NodeType.ATTRIBUTE_NODE,
nodeName: null,
name: null,
value: null,
typedValue: null,
};
const nsRef = this.readS32();
const nameRef = this.readS32();
const valueRef = this.readS32();
if (nsRef > 0) {
attr.namespaceURI = this.strings[nsRef];
}
attr.nodeName = attr.name = this.strings[nameRef];
if (valueRef > 0) {
attr.value = this.strings[valueRef];
}
attr.typedValue = this.readTypedValue();
return attr;
}
readXmlElementEnd( /* header */) {
// debug('readXmlCData');
this.readU32();
this.readU32();
this.readU32();
this.readU32();
// const line = this.readU32();
// const commentRef = this.readU32();
// const nsRef = this.readS32();
// const nameRef = this.readS32();
this.stack.pop();
this.parent = this.stack[this.stack.length - 1];
return null;
}
readXmlCData( /* header */) {
// debug('readXmlCData');
const cdata = {
namespaceURI: null,
nodeType: NodeType.CDATA_SECTION_NODE,
nodeName: '#cdata',
data: null,
typedValue: null,
};
this.readU32();
this.readU32();
// const line = this.readU32();
// const commentRef = this.readU32();
const dataRef = this.readS32();
if (dataRef > 0) {
cdata.data = this.strings[dataRef];
}
cdata.typedValue = this.readTypedValue();
this.parent.childNodes.push(cdata);
return cdata;
}
readNull(header) {
// debug('readNull');
this.cursor += header.chunkSize - header.headerSize;
return null;
}
parse() {
// debug('parse');
const xmlHeader = this.readChunkHeader();
if (xmlHeader.chunkType !== ChunkType.XML) {
throw new errors_1.Exception('Invalid XML header');
}
while (this.cursor < this.buffer.length) {
// debug('chunk');
const start = this.cursor;
const header = this.readChunkHeader();
switch (header.chunkType) {
case ChunkType.STRING_POOL:
this.readStringPool(header);
break;
case ChunkType.XML_RESOURCE_MAP:
this.readResourceMap(header);
break;
case ChunkType.XML_START_NAMESPACE:
this.readXmlNamespaceStart();
break;
case ChunkType.XML_END_NAMESPACE:
this.readXmlNamespaceEnd();
break;
case ChunkType.XML_START_ELEMENT:
this.readXmlElementStart();
break;
case ChunkType.XML_END_ELEMENT:
this.readXmlElementEnd();
break;
case ChunkType.XML_CDATA:
this.readXmlCData();
break;
case ChunkType.NULL:
this.readNull(header);
break;
default:
throw new errors_1.Exception(`Unsupported chunk type '${header.chunkType}'`);
}
// Ensure we consume the whole chunk
const end = start + header.chunkSize;
if (this.cursor !== end) {
// const diff = end - this.cursor;
// const type = header.chunkType.toString(16);
// debug(`Cursor is off by ${diff} bytes at ${this.cursor} at supposed \
// end of chunk of type 0x${type}. The chunk started at offset ${start} and is \
// supposed to end at offset ${end}. Ignoring the rest of the chunk.`);
// this.cursor = end;
}
}
return this.document;
}
}
exports.BinaryXmlParser = BinaryXmlParser;

204
node_modules/native-run/dist/android/utils/emulator.js generated vendored Normal file
View file

@ -0,0 +1,204 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseAndroidConsoleResponse = exports.getAVDFromEmulator = exports.parseEmulatorOutput = exports.EmulatorEvent = exports.spawnEmulator = exports.runEmulator = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const child_process_1 = require("child_process");
const Debug = require("debug");
const net = require("net");
const os = require("os");
const path = require("path");
const split2 = require("split2");
const through2 = require("through2");
const errors_1 = require("../../errors");
const fn_1 = require("../../utils/fn");
const adb_1 = require("./adb");
const sdk_1 = require("./sdk");
const modulePrefix = 'native-run:android:utils:emulator';
/**
* Resolves when emulator is ready and running with the specified AVD.
*/
async function runEmulator(sdk, avd, port) {
try {
await spawnEmulator(sdk, avd, port);
}
catch (e) {
if (!(e instanceof errors_1.EmulatorException) || e.code !== errors_1.ERR_ALREADY_RUNNING) {
throw e;
}
}
const serial = `emulator-${port}`;
const devices = await (0, adb_1.getDevices)(sdk);
const emulator = devices.find((device) => device.serial === serial);
if (!emulator) {
throw new errors_1.EmulatorException(`Emulator not found: ${serial}`);
}
return emulator;
}
exports.runEmulator = runEmulator;
async function spawnEmulator(sdk, avd, port) {
const debug = Debug(`${modulePrefix}:${spawnEmulator.name}`);
const emulator = await (0, sdk_1.getSDKPackage)(path.join(sdk.root, 'emulator'));
const emulatorBin = path.join(emulator.location, 'emulator');
const args = ['-avd', avd.id, '-port', port.toString(), '-verbose'];
debug('Invoking emulator: %O %O', emulatorBin, args);
const p = (0, child_process_1.spawn)(emulatorBin, args, {
detached: true,
stdio: ['ignore', 'pipe', 'pipe'],
env: (0, sdk_1.supplementProcessEnv)(sdk),
});
p.unref();
return new Promise((_resolve, _reject) => {
const resolve = (0, fn_1.once)(() => {
_resolve();
cleanup();
});
const reject = (0, fn_1.once)((err) => {
_reject(err);
cleanup();
});
(0, adb_1.waitForDevice)(sdk, `emulator-${port}`).then(() => resolve(), (err) => reject(err));
const eventParser = through2((chunk, enc, cb) => {
const line = chunk.toString();
debug('Android Emulator: %O', line);
const event = parseEmulatorOutput(line);
if (event === EmulatorEvent.AlreadyRunning) {
reject(new errors_1.EmulatorException(`Emulator already running with AVD [${avd.id}]`, errors_1.ERR_ALREADY_RUNNING));
}
else if (event === EmulatorEvent.UnknownAVD) {
reject(new errors_1.EmulatorException(`Unknown AVD name [${avd.id}]`, errors_1.ERR_UNKNOWN_AVD));
}
else if (event === EmulatorEvent.AVDHomeNotFound) {
reject(new errors_1.EmulatorException(`Emulator cannot find AVD home`, errors_1.ERR_AVD_HOME_NOT_FOUND));
}
cb();
});
const stdoutStream = p.stdout.pipe(split2());
const stderrStream = p.stderr.pipe(split2());
stdoutStream.pipe(eventParser);
stderrStream.pipe(eventParser);
const cleanup = () => {
debug('Unhooking stdout/stderr streams from emulator process');
p.stdout.push(null);
p.stderr.push(null);
};
p.on('close', (code) => {
debug('Emulator closed, exit code %d', code);
if (code) {
reject(new errors_1.EmulatorException(`Non-zero exit code from Emulator: ${code}`, errors_1.ERR_NON_ZERO_EXIT));
}
});
p.on('error', (err) => {
debug('Emulator error: %O', err);
reject(err);
});
});
}
exports.spawnEmulator = spawnEmulator;
var EmulatorEvent;
(function (EmulatorEvent) {
EmulatorEvent[EmulatorEvent["UnknownAVD"] = 0] = "UnknownAVD";
EmulatorEvent[EmulatorEvent["AlreadyRunning"] = 1] = "AlreadyRunning";
EmulatorEvent[EmulatorEvent["AVDHomeNotFound"] = 2] = "AVDHomeNotFound";
})(EmulatorEvent = exports.EmulatorEvent || (exports.EmulatorEvent = {}));
function parseEmulatorOutput(line) {
const debug = Debug(`${modulePrefix}:${parseEmulatorOutput.name}`);
let event;
if (line.includes('Unknown AVD name')) {
event = EmulatorEvent.UnknownAVD;
}
else if (line.includes('another emulator instance running with the current AVD')) {
event = EmulatorEvent.AlreadyRunning;
}
else if (line.includes('Cannot find AVD system path')) {
event = EmulatorEvent.AVDHomeNotFound;
}
if (typeof event !== 'undefined') {
debug('Parsed event from emulator output: %s', EmulatorEvent[event]);
}
return event;
}
exports.parseEmulatorOutput = parseEmulatorOutput;
async function getAVDFromEmulator(emulator, avds) {
const debug = Debug(`${modulePrefix}:${getAVDFromEmulator.name}`);
const emulatorPortRegex = /^emulator-(\d+)$/;
const m = emulator.serial.match(emulatorPortRegex);
if (!m) {
throw new errors_1.EmulatorException(`Emulator ${emulator.serial} does not match expected emulator serial format`);
}
const port = Number.parseInt(m[1], 10);
const host = 'localhost';
const sock = net.createConnection({ host, port });
sock.setEncoding('utf8');
sock.setTimeout(5000);
const readAuthFile = new Promise((resolve, reject) => {
sock.on('connect', () => {
debug('Connected to %s:%d', host, port);
(0, utils_fs_1.readFile)(path.resolve(os.homedir(), '.emulator_console_auth_token'), {
encoding: 'utf8',
}).then((contents) => resolve(contents.trim()), (err) => reject(err));
});
});
let Stage;
(function (Stage) {
Stage[Stage["Initial"] = 0] = "Initial";
Stage[Stage["Auth"] = 1] = "Auth";
Stage[Stage["AuthSuccess"] = 2] = "AuthSuccess";
Stage[Stage["Response"] = 3] = "Response";
Stage[Stage["Complete"] = 4] = "Complete";
})(Stage || (Stage = {}));
return new Promise((resolve, reject) => {
let stage = Stage.Initial;
const timer = setTimeout(() => {
if (stage !== Stage.Complete) {
reject(new errors_1.EmulatorException(`Took too long to get AVD name from Android Emulator Console, something went wrong.`));
}
}, 3000);
const cleanup = (0, fn_1.once)(() => {
clearTimeout(timer);
sock.end();
});
sock.on('timeout', () => {
reject(new errors_1.EmulatorException(`Socket timeout on ${host}:${port}`));
cleanup();
});
sock.pipe(split2()).pipe(through2((chunk, enc, cb) => {
const line = chunk.toString();
debug('Android Console: %O', line);
if (stage === Stage.Initial && line.includes('Authentication required')) {
stage = Stage.Auth;
}
else if (stage === Stage.Auth && line.trim() === 'OK') {
readAuthFile.then((token) => sock.write(`auth ${token}\n`, 'utf8'), (err) => reject(err));
stage = Stage.AuthSuccess;
}
else if (stage === Stage.AuthSuccess && line.trim() === 'OK') {
sock.write('avd name\n', 'utf8');
stage = Stage.Response;
}
else if (stage === Stage.Response) {
const avdId = line.trim();
const avd = avds.find((avd) => avd.id === avdId);
if (avd) {
resolve(avd);
}
else {
reject(new errors_1.EmulatorException(`Unknown AVD name [${avdId}]`, errors_1.ERR_UNKNOWN_AVD));
}
stage = Stage.Complete;
cleanup();
}
cb();
}));
});
}
exports.getAVDFromEmulator = getAVDFromEmulator;
function parseAndroidConsoleResponse(output) {
const debug = Debug(`${modulePrefix}:${parseAndroidConsoleResponse.name}`);
const m = /([\s\S]+)OK\r?\n/g.exec(output);
if (m) {
const [, response] = m;
debug('Parsed response data from Android Console output: %O', response);
return response;
}
}
exports.parseAndroidConsoleResponse = parseAndroidConsoleResponse;

32
node_modules/native-run/dist/android/utils/list.js generated vendored Normal file
View file

@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.avdToTarget = exports.deviceToTarget = exports.getVirtualTargets = exports.getDeviceTargets = void 0;
const adb_1 = require("./adb");
const avd_1 = require("./avd");
async function getDeviceTargets(sdk) {
return (await (0, adb_1.getDevices)(sdk)).filter((device) => device.type === 'hardware').map(deviceToTarget);
}
exports.getDeviceTargets = getDeviceTargets;
async function getVirtualTargets(sdk) {
const avds = await (0, avd_1.getInstalledAVDs)(sdk);
return avds.map(avdToTarget);
}
exports.getVirtualTargets = getVirtualTargets;
function deviceToTarget(device) {
return {
platform: 'android',
model: `${device.manufacturer} ${device.model}`,
sdkVersion: device.sdkVersion,
id: device.serial,
};
}
exports.deviceToTarget = deviceToTarget;
function avdToTarget(avd) {
return {
platform: 'android',
name: avd.name,
sdkVersion: avd.sdkVersion,
id: avd.id,
};
}
exports.avdToTarget = avdToTarget;

132
node_modules/native-run/dist/android/utils/run.js generated vendored Normal file
View file

@ -0,0 +1,132 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.installApkToDevice = exports.selectVirtualDevice = exports.selectHardwareDevice = exports.selectDeviceByTarget = exports.isLikelyEmulator = exports.findAvailableEmulatorPort = void 0;
const Debug = require("debug");
const errors_1 = require("../../errors");
const log_1 = require("../../utils/log");
const adb_1 = require("./adb");
const emulator_1 = require("./emulator");
const modulePrefix = 'native-run:android:utils:run';
async function findAvailableEmulatorPort(devices, start = 5554, end = 5584) {
const debug = Debug(`${modulePrefix}:${findAvailableEmulatorPort.name}`);
const usedPorts = new Set();
for (const d of devices) {
const m = d.serial.match(/^emulator-(\d+)$/);
if (m) {
usedPorts.add(Number(m[1]));
}
}
for (let port = start; port <= end; port += 2) {
if (!usedPorts.has(port)) {
debug('Available emulator port found: %d', port);
return port;
}
}
debug('No available emulator ports found in range %d-%d; defaulting to 5554', start, end);
return 5554;
}
exports.findAvailableEmulatorPort = findAvailableEmulatorPort;
function isLikelyEmulator(device) {
const serialEmu = /^emulator-(\d+)$/;
if (serialEmu.test(device.serial)) {
return true;
}
if (device.type === 'emulator') {
return true;
}
const props = device.properties || {};
const deviceProp = (props['device'] || '').toLowerCase();
const productProp = (props['product'] || '').toLowerCase();
const model = (device.model || '').toLowerCase();
if (deviceProp.startsWith('emu') || deviceProp.includes('generic')) {
return true;
}
if (productProp.includes('sdk_gphone') || productProp.includes('google_sdk')) {
return true;
}
if (model.includes('android_sdk') || model.includes('sdk_gphone')) {
return true;
}
return false;
}
exports.isLikelyEmulator = isLikelyEmulator;
async function selectDeviceByTarget(sdk, devices, avds, target) {
const debug = Debug(`${modulePrefix}:${selectDeviceByTarget.name}`);
debug('--target %s detected', target);
debug('Checking if device can be found by serial: %s', target);
const device = devices.find((d) => d.serial === target);
if (device) {
debug('Device found by serial: %s', device.serial);
return device;
}
const emulatorDevices = devices.filter(isLikelyEmulator);
const pairAVD = async (emulator) => {
let avd;
try {
avd = await (0, emulator_1.getAVDFromEmulator)(emulator, avds);
debug('Emulator %s is using AVD: %s', emulator.serial, avd.id);
}
catch (e) {
debug('Error with emulator %s: %O', emulator.serial, e);
}
return [emulator, avd];
};
debug('Checking if any of %d running emulators are using AVD by ID: %s', emulatorDevices.length, target);
const emulatorsAndAVDs = await Promise.all(emulatorDevices.map((emulator) => pairAVD(emulator)));
const emulators = emulatorsAndAVDs.filter((t) => typeof t[1] !== 'undefined');
const emulator = emulators.find(([, avd]) => avd.id === target);
if (emulator) {
const [device, avd] = emulator;
debug('Emulator %s found by AVD: %s', device.serial, avd.id);
return device;
}
debug('Checking if AVD can be found by ID: %s', target);
const avd = avds.find((avd) => avd.id === target);
if (avd) {
debug('AVD found by ID: %s', avd.id);
const port = await findAvailableEmulatorPort(devices);
debug('Using emulator port: %d', port);
const device = await (0, emulator_1.runEmulator)(sdk, avd, port);
debug('Emulator ready, running avd: %s on %s', avd.id, device.serial);
return device;
}
}
exports.selectDeviceByTarget = selectDeviceByTarget;
async function selectHardwareDevice(devices) {
const hardwareDevices = devices.filter((d) => d.type === 'hardware');
// If a hardware device is found, we prefer launching to it instead of in an emulator.
if (hardwareDevices.length > 0) {
return hardwareDevices[0]; // TODO: can probably do better analysis on which to use?
}
}
exports.selectHardwareDevice = selectHardwareDevice;
async function selectVirtualDevice(sdk, devices, avds) {
const debug = Debug(`${modulePrefix}:${selectVirtualDevice.name}`);
const emulators = devices.filter((d) => d.type === 'emulator');
// If an emulator is running, use it.
if (emulators.length > 0) {
const [emulator] = emulators;
debug('Found running emulator: %s', emulator.serial);
return emulator;
}
throw new errors_1.AndroidRunException('No target devices/emulators available.', errors_1.ERR_NO_TARGET);
}
exports.selectVirtualDevice = selectVirtualDevice;
async function installApkToDevice(sdk, device, apk, appId) {
(0, log_1.log)(`Installing ${apk}...\n`);
try {
await (0, adb_1.installApk)(sdk, device, apk);
}
catch (e) {
if (e instanceof errors_1.ADBException) {
if (e.code === errors_1.ERR_INCOMPATIBLE_UPDATE || e.code === errors_1.ERR_VERSION_DOWNGRADE) {
(0, log_1.log)(`${e.message} Uninstalling and trying again...\n`);
await (0, adb_1.uninstallApp)(sdk, device, appId);
await (0, adb_1.installApk)(sdk, device, apk);
return;
}
}
throw e;
}
}
exports.installApkToDevice = installApkToDevice;

47
node_modules/native-run/dist/android/utils/sdk/api.js generated vendored Normal file
View file

@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.findPackageBySchemaPath = exports.findPackageBySchema = exports.findUnsatisfiedPackages = exports.getAPILevels = void 0;
const Debug = require("debug");
const modulePrefix = 'native-run:android:utils:sdk:api';
async function getAPILevels(packages) {
const debug = Debug(`${modulePrefix}:${getAPILevels.name}`);
const levels = [
...new Set(packages.map((pkg) => pkg.apiLevel).filter((apiLevel) => typeof apiLevel !== 'undefined')),
].sort((a, b) => (a <= b ? 1 : -1));
const apis = levels.map((apiLevel) => ({
apiLevel,
packages: packages.filter((pkg) => pkg.apiLevel === apiLevel),
}));
debug('Discovered installed API Levels: %O', apis.map((api) => ({ ...api, packages: api.packages.map((pkg) => pkg.path) })));
return apis;
}
exports.getAPILevels = getAPILevels;
function findUnsatisfiedPackages(packages, schemas) {
return schemas.filter((pkg) => !findPackageBySchema(packages, pkg));
}
exports.findUnsatisfiedPackages = findUnsatisfiedPackages;
function findPackageBySchema(packages, pkg) {
const apiPkg = findPackageBySchemaPath(packages, pkg.path);
if (apiPkg) {
if (typeof pkg.version === 'string') {
if (pkg.version === apiPkg.version) {
return apiPkg;
}
}
else {
if (apiPkg.version.match(pkg.version)) {
return apiPkg;
}
}
}
}
exports.findPackageBySchema = findPackageBySchema;
function findPackageBySchemaPath(packages, path) {
return packages.find((pkg) => {
if (typeof path !== 'string') {
return !!pkg.path.match(path);
}
return path === pkg.path;
});
}
exports.findPackageBySchemaPath = findPackageBySchemaPath;

169
node_modules/native-run/dist/android/utils/sdk/index.js generated vendored Normal file
View file

@ -0,0 +1,169 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.supplementProcessEnv = exports.resolveAVDHome = exports.resolveEmulatorHome = exports.resolveSDKRoot = exports.getSDKPackage = exports.findAllSDKPackages = exports.getSDK = exports.SDK_DIRECTORIES = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const Debug = require("debug");
const os = require("os");
const pathlib = require("path");
const errors_1 = require("../../../errors");
const fs_1 = require("../../../utils/fs");
const xml_1 = require("./xml");
const modulePrefix = 'native-run:android:utils:sdk';
const homedir = os.homedir();
exports.SDK_DIRECTORIES = new Map([
['darwin', [pathlib.join(homedir, 'Library', 'Android', 'sdk')]],
['linux', [pathlib.join(homedir, 'Android', 'sdk')]],
['win32', [pathlib.join(process.env.LOCALAPPDATA || pathlib.join(homedir, 'AppData', 'Local'), 'Android', 'Sdk')]],
]);
async function getSDK() {
const root = await resolveSDKRoot();
const emulatorHome = await resolveEmulatorHome();
const avdHome = await resolveAVDHome();
return { root, emulatorHome, avdHome };
}
exports.getSDK = getSDK;
const pkgcache = new Map();
async function findAllSDKPackages(sdk) {
const debug = Debug(`${modulePrefix}:${findAllSDKPackages.name}`);
if (sdk.packages) {
return sdk.packages;
}
const sourcesRe = /^sources\/android-\d+\/.+\/.+/;
debug('Walking %s to discover SDK packages', sdk.root);
const contents = await (0, utils_fs_1.readdirp)(sdk.root, {
filter: (item) => pathlib.basename(item.path) === 'package.xml',
onError: (err) => debug('Error while walking SDK: %O', err),
walkerOptions: {
pathFilter: (p) => {
if ([
'bin',
'bin64',
'lib',
'lib64',
'include',
'clang-include',
'skins',
'data',
'examples',
'resources',
'systrace',
'extras',
// 'm2repository',
].includes(pathlib.basename(p))) {
return false;
}
if (p.match(sourcesRe)) {
return false;
}
return true;
},
},
});
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;
}
exports.findAllSDKPackages = findAllSDKPackages;
async function getSDKPackage(location) {
const debug = Debug(`${modulePrefix}:${getSDKPackage.name}`);
let pkg = pkgcache.get(location);
if (!pkg) {
const packageXmlPath = pathlib.join(location, 'package.xml');
debug('Parsing %s', packageXmlPath);
try {
const packageXml = await (0, xml_1.readPackageXml)(packageXmlPath);
const name = (0, xml_1.getNameFromPackageXml)(packageXml);
const version = (0, xml_1.getVersionFromPackageXml)(packageXml);
const path = (0, xml_1.getPathFromPackageXml)(packageXml);
const apiLevel = (0, xml_1.getAPILevelFromPackageXml)(packageXml);
pkg = {
path,
location,
version,
name,
apiLevel,
};
}
catch (e) {
debug('Encountered error with %s: %O', packageXmlPath, e);
if (e.code === 'ENOENT') {
throw new errors_1.SDKException(`SDK package not found by location: ${location}.`, errors_1.ERR_SDK_PACKAGE_NOT_FOUND);
}
throw e;
}
pkgcache.set(location, pkg);
}
return pkg;
}
exports.getSDKPackage = getSDKPackage;
async function resolveSDKRoot() {
const debug = Debug(`${modulePrefix}:${resolveSDKRoot.name}`);
debug('Looking for $ANDROID_HOME');
// $ANDROID_HOME is deprecated, but still overrides $ANDROID_SDK_ROOT if
// defined and valid.
if (process.env.ANDROID_HOME && (await (0, fs_1.isDir)(process.env.ANDROID_HOME))) {
debug('Using $ANDROID_HOME at %s', process.env.ANDROID_HOME);
return process.env.ANDROID_HOME;
}
debug('Looking for $ANDROID_SDK_ROOT');
// No valid $ANDROID_HOME, try $ANDROID_SDK_ROOT.
if (process.env.ANDROID_SDK_ROOT && (await (0, fs_1.isDir)(process.env.ANDROID_SDK_ROOT))) {
debug('Using $ANDROID_SDK_ROOT at %s', process.env.ANDROID_SDK_ROOT);
return process.env.ANDROID_SDK_ROOT;
}
const sdkDirs = exports.SDK_DIRECTORIES.get(process.platform);
if (!sdkDirs) {
throw new errors_1.SDKException(`Unsupported platform: ${process.platform}`);
}
debug('Looking at following directories: %O', sdkDirs);
for (const sdkDir of sdkDirs) {
if (await (0, fs_1.isDir)(sdkDir)) {
debug('Using %s', sdkDir);
return sdkDir;
}
}
throw new errors_1.SDKException(`No valid Android SDK root found.`, errors_1.ERR_SDK_NOT_FOUND);
}
exports.resolveSDKRoot = resolveSDKRoot;
async function resolveEmulatorHome() {
const debug = Debug(`${modulePrefix}:${resolveEmulatorHome.name}`);
debug('Looking for $ANDROID_EMULATOR_HOME');
if (process.env.ANDROID_EMULATOR_HOME && (await (0, fs_1.isDir)(process.env.ANDROID_EMULATOR_HOME))) {
debug('Using $ANDROID_EMULATOR_HOME at %s', process.env.ANDROID_EMULATOR_HOME);
return process.env.ANDROID_EMULATOR_HOME;
}
debug('Looking at $HOME/.android');
const homeEmulatorHome = pathlib.join(homedir, '.android');
if (await (0, fs_1.isDir)(homeEmulatorHome)) {
debug('Using $HOME/.android/ at %s', homeEmulatorHome);
return homeEmulatorHome;
}
throw new errors_1.SDKException(`No valid Android Emulator home found.`, errors_1.ERR_EMULATOR_HOME_NOT_FOUND);
}
exports.resolveEmulatorHome = resolveEmulatorHome;
async function resolveAVDHome() {
const debug = Debug(`${modulePrefix}:${resolveAVDHome.name}`);
debug('Looking for $ANDROID_AVD_HOME');
if (process.env.ANDROID_AVD_HOME && (await (0, fs_1.isDir)(process.env.ANDROID_AVD_HOME))) {
debug('Using $ANDROID_AVD_HOME at %s', process.env.ANDROID_AVD_HOME);
return process.env.ANDROID_AVD_HOME;
}
debug('Looking at $HOME/.android/avd');
const homeAvdHome = pathlib.join(homedir, '.android', 'avd');
if (!(await (0, fs_1.isDir)(homeAvdHome))) {
debug('Creating directory: %s', homeAvdHome);
await (0, utils_fs_1.mkdirp)(homeAvdHome);
}
debug('Using $HOME/.android/avd/ at %s', homeAvdHome);
return homeAvdHome;
}
exports.resolveAVDHome = resolveAVDHome;
function supplementProcessEnv(sdk) {
return {
...process.env,
ANDROID_SDK_ROOT: sdk.root,
ANDROID_EMULATOR_HOME: sdk.emulatorHome,
ANDROID_AVD_HOME: sdk.avdHome,
};
}
exports.supplementProcessEnv = supplementProcessEnv;

58
node_modules/native-run/dist/android/utils/sdk/xml.js generated vendored Normal file
View file

@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getVersionFromPackageXml = exports.getNameFromPackageXml = exports.getPathFromPackageXml = exports.readPackageXml = exports.getAPILevelFromPackageXml = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const errors_1 = require("../../../errors");
function getAPILevelFromPackageXml(packageXml) {
var _a;
const apiLevel = packageXml.find('./localPackage/type-details/api-level');
return (_a = apiLevel === null || apiLevel === void 0 ? void 0 : apiLevel.text) === null || _a === void 0 ? void 0 : _a.toString();
}
exports.getAPILevelFromPackageXml = getAPILevelFromPackageXml;
async function readPackageXml(path) {
const et = await Promise.resolve().then(() => require('elementtree'));
const contents = await (0, utils_fs_1.readFile)(path, { encoding: 'utf8' });
const etree = et.parse(contents);
return etree;
}
exports.readPackageXml = readPackageXml;
function getPathFromPackageXml(packageXml) {
const localPackage = packageXml.find('./localPackage');
if (!localPackage) {
throw new errors_1.SDKException(`Invalid SDK package.`, errors_1.ERR_INVALID_SDK_PACKAGE);
}
const path = localPackage.get('path');
if (!path) {
throw new errors_1.SDKException(`Invalid SDK package path.`, errors_1.ERR_INVALID_SDK_PACKAGE);
}
return path.toString();
}
exports.getPathFromPackageXml = getPathFromPackageXml;
function getNameFromPackageXml(packageXml) {
const name = packageXml.find('./localPackage/display-name');
if (!(name === null || name === void 0 ? void 0 : name.text)) {
throw new errors_1.SDKException(`Invalid SDK package name.`, errors_1.ERR_INVALID_SDK_PACKAGE);
}
return name.text.toString();
}
exports.getNameFromPackageXml = getNameFromPackageXml;
function getVersionFromPackageXml(packageXml) {
const versionElements = [
packageXml.find('./localPackage/revision/major'),
packageXml.find('./localPackage/revision/minor'),
packageXml.find('./localPackage/revision/micro'),
];
const textFromElement = (e) => ((e === null || e === void 0 ? void 0 : e.text) ? e.text.toString() : '');
const versions = [];
for (const version of versionElements.map(textFromElement)) {
if (!version) {
break;
}
versions.push(version);
}
if (versions.length === 0) {
throw new errors_1.SDKException(`Invalid SDK package version.`, errors_1.ERR_INVALID_SDK_PACKAGE);
}
return versions.join('.');
}
exports.getVersionFromPackageXml = getVersionFromPackageXml;

5
node_modules/native-run/dist/constants.js generated vendored Normal file
View file

@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ASSETS_PATH = void 0;
const pathlib = require("path");
exports.ASSETS_PATH = pathlib.resolve(__dirname, '..', 'assets');

81
node_modules/native-run/dist/errors.js generated vendored Normal file
View file

@ -0,0 +1,81 @@
"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_UNKNOWN_AVD = exports.ERR_DEVICE_LOCKED = exports.ERR_NO_TARGET = exports.ERR_NO_DEVICE = exports.ERR_TARGET_NOT_FOUND = exports.ERR_SDK_PACKAGE_NOT_FOUND = exports.ERR_SDK_NOT_FOUND = exports.ERR_UNSUITABLE_API_INSTALLATION = exports.ERR_NON_ZERO_EXIT = 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");
class Exception extends Error {
constructor(message, code, exitCode = 1 /* ExitCode.GENERAL */, data) {
super(message);
this.message = message;
this.code = code;
this.exitCode = exitCode;
this.data = data;
}
serialize() {
return `${this.code ? this.code : 'ERR_UNKNOWN'}: ${this.message}`;
}
toJSON() {
return {
error: this.message,
code: this.code,
...this.data,
};
}
}
exports.Exception = Exception;
class AndroidException extends Exception {
serialize() {
return (`${super.serialize()}\n\n` +
`\tMore details for this error may be available online:\n\n` +
`\thttps://github.com/ionic-team/native-run/wiki/Android-Errors`);
}
}
exports.AndroidException = AndroidException;
exports.ERR_BAD_INPUT = 'ERR_BAD_INPUT';
exports.ERR_ALREADY_RUNNING = 'ERR_ALREADY_RUNNING ';
exports.ERR_AVD_HOME_NOT_FOUND = 'ERR_AVD_HOME_NOT_FOUND';
exports.ERR_EMULATOR_HOME_NOT_FOUND = 'ERR_EMULATOR_HOME_NOT_FOUND';
exports.ERR_INCOMPATIBLE_UPDATE = 'ERR_INCOMPATIBLE_UPDATE';
exports.ERR_VERSION_DOWNGRADE = 'ERR_VERSION_DOWNGRADE';
exports.ERR_MIN_SDK_VERSION = 'ERR_MIN_SDK_VERSION';
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';
exports.ERR_NON_ZERO_EXIT = 'ERR_NON_ZERO_EXIT';
exports.ERR_UNSUITABLE_API_INSTALLATION = 'ERR_UNSUITABLE_API_INSTALLATION';
exports.ERR_SDK_NOT_FOUND = 'ERR_SDK_NOT_FOUND';
exports.ERR_SDK_PACKAGE_NOT_FOUND = 'ERR_SDK_PACKAGE_NOT_FOUND';
exports.ERR_TARGET_NOT_FOUND = 'ERR_TARGET_NOT_FOUND';
exports.ERR_NO_DEVICE = 'ERR_NO_DEVICE';
exports.ERR_NO_TARGET = 'ERR_NO_TARGET';
exports.ERR_DEVICE_LOCKED = 'ERR_DEVICE_LOCKED';
exports.ERR_UNKNOWN_AVD = 'ERR_UNKNOWN_AVD';
class CLIException extends Exception {
}
exports.CLIException = CLIException;
class ADBException extends AndroidException {
}
exports.ADBException = ADBException;
class AVDException extends AndroidException {
}
exports.AVDException = AVDException;
class EmulatorException extends AndroidException {
}
exports.EmulatorException = EmulatorException;
class AndroidRunException extends AndroidException {
}
exports.AndroidRunException = AndroidRunException;
class SDKException extends AndroidException {
}
exports.SDKException = SDKException;
class IOSRunException extends Exception {
}
exports.IOSRunException = IOSRunException;
function serializeError(e = new Error()) {
const stack = String(e.stack ? e.stack : e);
if (process.argv.includes('--json')) {
return (0, json_1.stringify)(e instanceof Exception ? e : { error: stack });
}
return (e instanceof Exception ? e.serialize() : stack) + '\n';
}
exports.serializeError = serializeError;

18
node_modules/native-run/dist/help.js generated vendored Normal file
View file

@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = void 0;
const help = `
Usage: native-run [ios|android] [options]
Options:
-h, --help ........... Print help for the platform, then quit
--version ............ Print version, then quit
--verbose ............ Print verbose output to stderr
--list ............... Print connected devices and virtual devices
`;
async function run(args) {
process.stdout.write(help);
}
exports.run = run;

49
node_modules/native-run/dist/index.js generated vendored Normal file
View file

@ -0,0 +1,49 @@
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = void 0;
const Debug = require("debug");
const path = require("path");
const errors_1 = require("./errors");
const debug = Debug('native-run');
async function run() {
const args = process.argv.slice(2);
if (args.includes('--version')) {
const pkg = await (_a = path.resolve(__dirname, '../package.json'), Promise.resolve().then(() => require(_a)));
process.stdout.write(pkg.version + '\n');
return;
}
let cmd;
const [platform, ...platformArgs] = args;
try {
if (platform === 'android') {
cmd = await Promise.resolve().then(() => require('./android'));
await cmd.run(platformArgs);
}
else if (platform === 'ios') {
cmd = await Promise.resolve().then(() => require('./ios'));
await cmd.run(platformArgs);
}
else if (platform === '--list') {
cmd = await Promise.resolve().then(() => require('./list'));
await cmd.run(args);
}
else {
if (!platform ||
platform === 'help' ||
args.includes('--help') ||
args.includes('-h') ||
platform.startsWith('-')) {
cmd = await Promise.resolve().then(() => require('./help'));
return cmd.run(args);
}
throw new errors_1.CLIException(`Unsupported platform: "${platform}"`, errors_1.ERR_BAD_INPUT);
}
}
catch (e) {
debug('Caught fatal error: %O', e);
process.exitCode = e instanceof errors_1.Exception ? e.exitCode : 1 /* ExitCode.GENERAL */;
process.stdout.write((0, errors_1.serializeError)(e));
}
}
exports.run = run;

35
node_modules/native-run/dist/ios/help.js generated vendored Normal file
View file

@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = void 0;
const help = `
Usage: native-run ios [options]
Run an .app or .ipa on a device or simulator target
Targets are selected as follows:
1) --target using device/simulator UUID
2) A connected device, unless --virtual is used
3) A running simulator
If the above criteria are not met, the app is run on the default simulator
(the last simulator in the list).
Use --list to list available targets.
Options:
--list ............... Print available targets, then quit
--json ............... Output JSON
--app <path> ......... Deploy specified .app or .ipa file
--device ............. Use a device if available
With --list prints connected devices
--virtual ............ Prefer a simulator
With --list prints available simulators
--target <id> ........ Use a specific target
--connect ............ Tie process to app process
`;
async function run() {
process.stdout.write(`${help}\n`);
}
exports.run = run;

17
node_modules/native-run/dist/ios/index.js generated vendored Normal file
View file

@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = void 0;
async function run(args) {
let cmd;
if (args.includes('--help') || args.includes('-h')) {
cmd = await Promise.resolve().then(() => require('./help'));
return cmd.run(args);
}
if (args.includes('--list') || args.includes('-l')) {
cmd = await Promise.resolve().then(() => require('./list'));
return cmd.run(args);
}
cmd = await Promise.resolve().then(() => require('./run'));
await cmd.run(args);
}
exports.run = run;

164
node_modules/native-run/dist/ios/lib/client/afc.js generated vendored Normal file
View file

@ -0,0 +1,164 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AFCClient = void 0;
const Debug = require("debug");
const fs = require("fs");
const path = require("path");
const util_1 = require("util");
const afc_1 = require("../protocol/afc");
const client_1 = require("./client");
const debug = Debug('native-run:ios:lib:client:afc');
const MAX_OPEN_FILES = 240;
class AFCClient extends client_1.ServiceClient {
constructor(socket) {
super(socket, new afc_1.AFCProtocolClient(socket));
this.socket = socket;
}
async getFileInfo(path) {
debug(`getFileInfo: ${path}`);
const resp = await this.protocolClient.sendMessage({
operation: afc_1.AFC_OPS.GET_FILE_INFO,
data: toCString(path),
});
const strings = [];
let currentString = '';
const tokens = resp.data;
tokens.forEach((token) => {
if (token === 0) {
strings.push(currentString);
currentString = '';
}
else {
currentString += String.fromCharCode(token);
}
});
return strings;
}
async writeFile(fd, data) {
debug(`writeFile: ${Array.prototype.toString.call(fd)}`);
return this.protocolClient.sendMessage({
operation: afc_1.AFC_OPS.FILE_WRITE,
data: fd,
payload: data,
});
}
async openFile(path) {
debug(`openFile: ${path}`);
// mode + path + null terminator
const data = Buffer.alloc(8 + Buffer.byteLength(path) + 1);
// write mode
data.writeUInt32LE(afc_1.AFC_FILE_OPEN_FLAGS.WRONLY, 0);
// then path to file
toCString(path).copy(data, 8);
const resp = await this.protocolClient.sendMessage({
operation: afc_1.AFC_OPS.FILE_OPEN,
data,
});
if (resp.operation === afc_1.AFC_OPS.FILE_OPEN_RES) {
return resp.data;
}
throw new Error(`There was an unknown error opening file ${path}, response: ${Array.prototype.toString.call(resp.data)}`);
}
async closeFile(fd) {
debug(`closeFile fd: ${Array.prototype.toString.call(fd)}`);
return this.protocolClient.sendMessage({
operation: afc_1.AFC_OPS.FILE_CLOSE,
data: fd,
});
}
async uploadFile(srcPath, destPath) {
debug(`uploadFile: ${srcPath}`);
// read local file and get fd of destination
const [srcFile, destFile] = await Promise.all([
await (0, util_1.promisify)(fs.readFile)(srcPath),
await this.openFile(destPath),
]);
try {
await this.writeFile(destFile, srcFile);
await this.closeFile(destFile);
}
catch (err) {
await this.closeFile(destFile);
throw err;
}
}
async makeDirectory(path) {
debug(`makeDirectory: ${path}`);
return this.protocolClient.sendMessage({
operation: afc_1.AFC_OPS.MAKE_DIR,
data: toCString(path),
});
}
async uploadDirectory(srcPath, destPath) {
debug(`uploadDirectory: ${srcPath}`);
await this.makeDirectory(destPath);
// AFC doesn't seem to give out more than 240 file handles,
// so we delay any requests that would push us over until more open up
let numOpenFiles = 0;
const pendingFileUploads = [];
const _this = this;
return uploadDir(srcPath);
async function uploadDir(dirPath) {
const promises = [];
for (const file of fs.readdirSync(dirPath)) {
const filePath = path.join(dirPath, file);
const remotePath = path.join(destPath, path.relative(srcPath, filePath));
if (fs.lstatSync(filePath).isDirectory()) {
promises.push(_this.makeDirectory(remotePath).then(() => uploadDir(filePath)));
}
else {
// Create promise to add to promises array
// this way it can be resolved once a pending upload has finished
let resolve;
let reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
promises.push(promise);
// wrap upload in a function in case we need to save it for later
const uploadFile = (tries = 0) => {
numOpenFiles++;
_this
.uploadFile(filePath, remotePath)
.then(() => {
resolve();
numOpenFiles--;
const fn = pendingFileUploads.pop();
if (fn) {
fn();
}
})
.catch((err) => {
// Couldn't get fd for whatever reason, try again
// # of retries is arbitrary and can be adjusted
if (err.status === afc_1.AFC_STATUS.NO_RESOURCES && tries < 10) {
debug(`Received NO_RESOURCES from AFC, retrying ${filePath} upload. ${tries}`);
uploadFile(tries++);
}
else {
numOpenFiles--;
reject(err);
}
});
};
if (numOpenFiles < MAX_OPEN_FILES) {
uploadFile();
}
else {
debug(`numOpenFiles >= ${MAX_OPEN_FILES}, adding to pending queue. Length: ${pendingFileUploads.length}`);
pendingFileUploads.push(uploadFile);
}
}
}
await Promise.all(promises);
}
}
}
exports.AFCClient = AFCClient;
function toCString(s) {
const buf = Buffer.alloc(Buffer.byteLength(s) + 1);
const len = buf.write(s);
buf.writeUInt8(0, len);
return buf;
}

17
node_modules/native-run/dist/ios/lib/client/client.js generated vendored Normal file
View file

@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ResponseError = exports.ServiceClient = void 0;
class ServiceClient {
constructor(socket, protocolClient) {
this.socket = socket;
this.protocolClient = protocolClient;
}
}
exports.ServiceClient = ServiceClient;
class ResponseError extends Error {
constructor(msg, response) {
super(msg);
this.response = response;
}
}
exports.ResponseError = ResponseError;

View file

@ -0,0 +1,66 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DebugserverClient = void 0;
const Debug = require("debug");
const path = require("path");
const gdb_1 = require("../protocol/gdb");
const client_1 = require("./client");
const debug = Debug('native-run:ios:lib:client:debugserver');
class DebugserverClient extends client_1.ServiceClient {
constructor(socket) {
super(socket, new gdb_1.GDBProtocolClient(socket));
this.socket = socket;
}
async setMaxPacketSize(size) {
return this.sendCommand('QSetMaxPacketSize:', [size.toString()]);
}
async setWorkingDir(workingDir) {
return this.sendCommand('QSetWorkingDir:', [workingDir]);
}
async checkLaunchSuccess() {
return this.sendCommand('qLaunchSuccess', []);
}
async attachByName(name) {
const hexName = Buffer.from(name).toString('hex');
return this.sendCommand(`vAttachName;${hexName}`, []);
}
async continue() {
return this.sendCommand('c', []);
}
halt() {
// ^C
debug('Sending ^C to debugserver');
return this.protocolClient.socket.write('\u0003');
}
async kill() {
const msg = { cmd: 'k', args: [] };
return this.protocolClient.sendMessage(msg, (resp, resolve, reject) => {
this.protocolClient.socket.write('+');
const parts = resp.split(';');
for (const part of parts) {
if (part.includes('description')) {
// description:{hex encoded message like: "Terminated with signal 9"}
resolve(Buffer.from(part.split(':')[1], 'hex').toString('ascii'));
}
}
});
}
// TODO support app args
// https://sourceware.org/gdb/onlinedocs/gdb/Packets.html#Packets
// A arglen,argnum,arg,
async launchApp(appPath, executableName) {
const fullPath = path.join(appPath, executableName);
const hexAppPath = Buffer.from(fullPath).toString('hex');
const appCommand = `A${hexAppPath.length},0,${hexAppPath}`;
return this.sendCommand(appCommand, []);
}
async sendCommand(cmd, args) {
const msg = { cmd, args };
debug(`Sending command: ${cmd}, args: ${args}`);
const resp = await this.protocolClient.sendMessage(msg);
// we need to ACK as well
this.protocolClient.socket.write('+');
return resp;
}
}
exports.DebugserverClient = DebugserverClient;

10
node_modules/native-run/dist/ios/lib/client/index.js generated vendored Normal file
View file

@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./client"), exports);
tslib_1.__exportStar(require("./afc"), exports);
tslib_1.__exportStar(require("./debugserver"), exports);
tslib_1.__exportStar(require("./installation_proxy"), exports);
tslib_1.__exportStar(require("./lockdownd"), exports);
tslib_1.__exportStar(require("./mobile_image_mounter"), exports);
tslib_1.__exportStar(require("./usbmuxd"), exports);

View file

@ -0,0 +1,72 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.InstallationProxyClient = void 0;
const Debug = require("debug");
const lockdown_1 = require("../protocol/lockdown");
const client_1 = require("./client");
const debug = Debug('native-run:ios:lib:client:installation_proxy');
function isIPLookupResponse(resp) {
return resp.length && resp[0].LookupResult !== undefined;
}
function isIPInstallPercentCompleteResponse(resp) {
return resp.length && resp[0].PercentComplete !== undefined;
}
function isIPInstallCFBundleIdentifierResponse(resp) {
return resp.length && resp[0].CFBundleIdentifier !== undefined;
}
function isIPInstallCompleteResponse(resp) {
return resp.length && resp[0].Status === 'Complete';
}
class InstallationProxyClient extends client_1.ServiceClient {
constructor(socket) {
super(socket, new lockdown_1.LockdownProtocolClient(socket));
this.socket = socket;
}
async lookupApp(bundleIds, options = {
ReturnAttributes: ['Path', 'Container', 'CFBundleExecutable', 'CFBundleIdentifier'],
ApplicationsType: 'Any',
}) {
debug(`lookupApp, options: ${JSON.stringify(options)}`);
const resp = await this.protocolClient.sendMessage({
Command: 'Lookup',
ClientOptions: {
BundleIDs: bundleIds,
...options,
},
});
if (isIPLookupResponse(resp)) {
return resp[0].LookupResult;
}
else {
throw new client_1.ResponseError(`There was an error looking up app`, resp);
}
}
async installApp(packagePath, bundleId, options = {
ApplicationsType: 'Any',
PackageType: 'Developer',
}) {
debug(`installApp, packagePath: ${packagePath}, bundleId: ${bundleId}`);
return this.protocolClient.sendMessage({
Command: 'Install',
PackagePath: packagePath,
ClientOptions: {
CFBundleIdentifier: bundleId,
...options,
},
}, (resp, resolve, reject) => {
if (isIPInstallCompleteResponse(resp)) {
resolve();
}
else if (isIPInstallPercentCompleteResponse(resp)) {
debug(`Installation status: ${resp[0].Status}, %${resp[0].PercentComplete}`);
}
else if (isIPInstallCFBundleIdentifierResponse(resp)) {
debug(`Installed app: ${resp[0].CFBundleIdentifier}`);
}
else {
reject(new client_1.ResponseError('There was an error installing app', resp));
}
});
}
}
exports.InstallationProxyClient = InstallationProxyClient;

View file

@ -0,0 +1,111 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LockdowndClient = void 0;
const Debug = require("debug");
const tls = require("tls");
const lockdown_1 = require("../protocol/lockdown");
const client_1 = require("./client");
const debug = Debug('native-run:ios:lib:client:lockdownd');
function isLockdowndServiceResponse(resp) {
return resp.Request === 'StartService' && resp.Service !== undefined && resp.Port !== undefined;
}
function isLockdowndSessionResponse(resp) {
return resp.Request === 'StartSession';
}
function isLockdowndAllValuesResponse(resp) {
return resp.Request === 'GetValue' && resp.Value !== undefined;
}
function isLockdowndValueResponse(resp) {
return resp.Request === 'GetValue' && resp.Key !== undefined && typeof resp.Value === 'string';
}
function isLockdowndQueryTypeResponse(resp) {
return resp.Request === 'QueryType' && resp.Type !== undefined;
}
class LockdowndClient extends client_1.ServiceClient {
constructor(socket) {
super(socket, new lockdown_1.LockdownProtocolClient(socket));
this.socket = socket;
}
async startService(name) {
debug(`startService: ${name}`);
const resp = await this.protocolClient.sendMessage({
Request: 'StartService',
Service: name,
});
if (isLockdowndServiceResponse(resp)) {
return { port: resp.Port, enableServiceSSL: !!resp.EnableServiceSSL };
}
else {
throw new client_1.ResponseError(`Error starting service ${name}`, resp);
}
}
async startSession(pairRecord) {
debug(`startSession: ${pairRecord}`);
const resp = await this.protocolClient.sendMessage({
Request: 'StartSession',
HostID: pairRecord.HostID,
SystemBUID: pairRecord.SystemBUID,
});
if (isLockdowndSessionResponse(resp)) {
if (resp.EnableSessionSSL) {
this.protocolClient.socket = new tls.TLSSocket(this.protocolClient.socket, {
secureContext: tls.createSecureContext({
secureProtocol: 'TLSv1_2_method',
cert: pairRecord.RootCertificate,
key: pairRecord.RootPrivateKey,
}),
});
debug(`Socket upgraded to TLS connection`);
}
// TODO: save sessionID for StopSession?
}
else {
throw new client_1.ResponseError('Error starting session', resp);
}
}
async getAllValues() {
debug(`getAllValues`);
const resp = await this.protocolClient.sendMessage({ Request: 'GetValue' });
if (isLockdowndAllValuesResponse(resp)) {
return resp.Value;
}
else {
throw new client_1.ResponseError('Error getting lockdown value', resp);
}
}
async getValue(val) {
debug(`getValue: ${val}`);
const resp = await this.protocolClient.sendMessage({
Request: 'GetValue',
Key: val,
});
if (isLockdowndValueResponse(resp)) {
return resp.Value;
}
else {
throw new client_1.ResponseError('Error getting lockdown value', resp);
}
}
async queryType() {
debug('queryType');
const resp = await this.protocolClient.sendMessage({
Request: 'QueryType',
});
if (isLockdowndQueryTypeResponse(resp)) {
return resp.Type;
}
else {
throw new client_1.ResponseError('Error getting lockdown query type', resp);
}
}
async doHandshake(pairRecord) {
debug('doHandshake');
// if (await this.lockdownQueryType() !== 'com.apple.mobile.lockdown') {
// throw new Error('Invalid type received from lockdown handshake');
// }
// await this.getLockdownValue('ProductVersion');
// TODO: validate pair and pair
await this.startSession(pairRecord);
}
}
exports.LockdowndClient = LockdowndClient;

View file

@ -0,0 +1,61 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MobileImageMounterClient = void 0;
const Debug = require("debug");
const fs = require("fs");
const lockdown_1 = require("../protocol/lockdown");
const client_1 = require("./client");
const debug = Debug('native-run:ios:lib:client:mobile_image_mounter');
function isMIMUploadCompleteResponse(resp) {
return resp.Status === 'Complete';
}
function isMIMUploadReceiveBytesResponse(resp) {
return resp.Status === 'ReceiveBytesAck';
}
class MobileImageMounterClient extends client_1.ServiceClient {
constructor(socket) {
super(socket, new lockdown_1.LockdownProtocolClient(socket));
}
async mountImage(imagePath, imageSig) {
debug(`mountImage: ${imagePath}`);
const resp = await this.protocolClient.sendMessage({
Command: 'MountImage',
ImagePath: imagePath,
ImageSignature: imageSig,
ImageType: 'Developer',
});
if (!(0, lockdown_1.isLockdownResponse)(resp) || resp.Status !== 'Complete') {
throw new client_1.ResponseError(`There was an error mounting ${imagePath} on device`, resp);
}
}
async uploadImage(imagePath, imageSig) {
debug(`uploadImage: ${imagePath}`);
const imageSize = fs.statSync(imagePath).size;
return this.protocolClient.sendMessage({
Command: 'ReceiveBytes',
ImageSize: imageSize,
ImageSignature: imageSig,
ImageType: 'Developer',
}, (resp, resolve, reject) => {
if (isMIMUploadReceiveBytesResponse(resp)) {
const imageStream = fs.createReadStream(imagePath);
imageStream.pipe(this.protocolClient.socket, { end: false });
imageStream.on('error', (err) => reject(err));
}
else if (isMIMUploadCompleteResponse(resp)) {
resolve();
}
else {
reject(new client_1.ResponseError(`There was an error uploading image ${imagePath} to the device`, resp));
}
});
}
async lookupImage() {
debug('lookupImage');
return this.protocolClient.sendMessage({
Command: 'LookupImage',
ImageType: 'Developer',
});
}
}
exports.MobileImageMounterClient = MobileImageMounterClient;

103
node_modules/native-run/dist/ios/lib/client/usbmuxd.js generated vendored Normal file
View file

@ -0,0 +1,103 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UsbmuxdClient = void 0;
const Debug = require("debug");
const net = require("net");
const plist = require("plist");
const usbmux_1 = require("../protocol/usbmux");
const client_1 = require("./client");
const debug = Debug('native-run:ios:lib:client:usbmuxd');
function isUsbmuxdConnectResponse(resp) {
return resp.MessageType === 'Result' && resp.Number !== undefined;
}
function isUsbmuxdDeviceResponse(resp) {
return resp.DeviceList !== undefined;
}
function isUsbmuxdPairRecordResponse(resp) {
return resp.PairRecordData !== undefined;
}
class UsbmuxdClient extends client_1.ServiceClient {
constructor(socket) {
super(socket, new usbmux_1.UsbmuxProtocolClient(socket));
this.socket = socket;
}
static connectUsbmuxdSocket() {
debug('connectUsbmuxdSocket');
if ('win32' === process.platform) {
return net.connect({ port: 27015, host: 'localhost' });
}
else {
return net.connect({ path: '/var/run/usbmuxd' });
}
}
async connect(device, port) {
debug(`connect: ${device.DeviceID} on port ${port}`);
const resp = await this.protocolClient.sendMessage({
messageType: 'Connect',
extraFields: {
DeviceID: device.DeviceID,
PortNumber: htons(port),
},
});
if (isUsbmuxdConnectResponse(resp) && resp.Number === 0) {
return this.protocolClient.socket;
}
else {
throw new client_1.ResponseError(`There was an error connecting to ${device.DeviceID} on port ${port}`, resp);
}
}
async getDevices() {
debug('getDevices');
const resp = await this.protocolClient.sendMessage({
messageType: 'ListDevices',
});
if (isUsbmuxdDeviceResponse(resp)) {
return resp.DeviceList;
}
else {
throw new client_1.ResponseError('Invalid response from getDevices', resp);
}
}
async getDevice(udid) {
debug(`getDevice ${udid ? 'udid: ' + udid : ''}`);
const devices = await this.getDevices();
if (!devices.length) {
throw new Error('No devices found');
}
if (!udid) {
return devices[0];
}
for (const device of devices) {
if (device.Properties && device.Properties.SerialNumber === udid) {
return device;
}
}
throw new Error(`No device with udid ${udid} found`);
}
async readPairRecord(udid) {
debug(`readPairRecord: ${udid}`);
const resp = await this.protocolClient.sendMessage({
messageType: 'ReadPairRecord',
extraFields: { PairRecordID: udid },
});
if (isUsbmuxdPairRecordResponse(resp)) {
// the pair record can be created as a binary plist
const BPLIST_MAGIC = Buffer.from('bplist00');
if (BPLIST_MAGIC.compare(resp.PairRecordData, 0, 8) === 0) {
debug('Binary plist pair record detected.');
const bplistParser = await Promise.resolve().then(() => require('bplist-parser'));
return bplistParser.parseBuffer(resp.PairRecordData)[0];
}
else {
return plist.parse(resp.PairRecordData.toString()); // TODO: type guard
}
}
else {
throw new client_1.ResponseError(`There was an error reading pair record for udid: ${udid}`, resp);
}
}
}
exports.UsbmuxdClient = UsbmuxdClient;
function htons(n) {
return ((n & 0xff) << 8) | ((n >> 8) & 0xff);
}

6
node_modules/native-run/dist/ios/lib/index.js generated vendored Normal file
View file

@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./client"), exports);
tslib_1.__exportStar(require("./protocol"), exports);
tslib_1.__exportStar(require("./manager"), exports);

10
node_modules/native-run/dist/ios/lib/lib-errors.js generated vendored Normal file
View file

@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.IOSLibError = void 0;
class IOSLibError extends Error {
constructor(message, code) {
super(message);
this.code = code;
}
}
exports.IOSLibError = IOSLibError;

139
node_modules/native-run/dist/ios/lib/manager.js generated vendored Normal file
View file

@ -0,0 +1,139 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClientManager = void 0;
const stream_1 = require("stream");
const tls = require("tls");
const afc_1 = require("./client/afc");
const debugserver_1 = require("./client/debugserver");
const installation_proxy_1 = require("./client/installation_proxy");
const lockdownd_1 = require("./client/lockdownd");
const mobile_image_mounter_1 = require("./client/mobile_image_mounter");
const usbmuxd_1 = require("./client/usbmuxd");
class ClientManager {
constructor(pairRecord, device, lockdowndClient) {
this.pairRecord = pairRecord;
this.device = device;
this.lockdowndClient = lockdowndClient;
this.connections = [lockdowndClient.socket];
}
static async create(udid) {
const usbmuxClient = new usbmuxd_1.UsbmuxdClient(usbmuxd_1.UsbmuxdClient.connectUsbmuxdSocket());
const device = await usbmuxClient.getDevice(udid);
const pairRecord = await usbmuxClient.readPairRecord(device.Properties.SerialNumber);
const lockdownSocket = await usbmuxClient.connect(device, 62078);
const lockdownClient = new lockdownd_1.LockdowndClient(lockdownSocket);
await lockdownClient.doHandshake(pairRecord);
return new ClientManager(pairRecord, device, lockdownClient);
}
async getUsbmuxdClient() {
const usbmuxClient = new usbmuxd_1.UsbmuxdClient(usbmuxd_1.UsbmuxdClient.connectUsbmuxdSocket());
this.connections.push(usbmuxClient.socket);
return usbmuxClient;
}
async getLockdowndClient() {
const usbmuxClient = new usbmuxd_1.UsbmuxdClient(usbmuxd_1.UsbmuxdClient.connectUsbmuxdSocket());
const lockdownSocket = await usbmuxClient.connect(this.device, 62078);
const lockdownClient = new lockdownd_1.LockdowndClient(lockdownSocket);
this.connections.push(lockdownClient.socket);
return lockdownClient;
}
async getLockdowndClientWithHandshake() {
const lockdownClient = await this.getLockdowndClient();
await lockdownClient.doHandshake(this.pairRecord);
return lockdownClient;
}
async getAFCClient() {
return this.getServiceClient('com.apple.afc', afc_1.AFCClient);
}
async getInstallationProxyClient() {
return this.getServiceClient('com.apple.mobile.installation_proxy', installation_proxy_1.InstallationProxyClient);
}
async getMobileImageMounterClient() {
return this.getServiceClient('com.apple.mobile.mobile_image_mounter', mobile_image_mounter_1.MobileImageMounterClient);
}
async getDebugserverClient() {
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 usbmuxClient = new usbmuxd_1.UsbmuxdClient(usbmuxd_1.UsbmuxdClient.connectUsbmuxdSocket());
let usbmuxdSocket = await usbmuxClient.connect(this.device, servicePort);
if (enableServiceSSL) {
const tlsOptions = {
rejectUnauthorized: false,
secureContext: tls.createSecureContext({
secureProtocol: 'TLSv1_2_method',
cert: this.pairRecord.RootCertificate,
key: this.pairRecord.RootPrivateKey,
}),
};
// Some services seem to not support TLS/SSL after the initial handshake
// More info: https://github.com/libimobiledevice/libimobiledevice/issues/793
if (disableSSL) {
// According to https://nodejs.org/api/tls.html#tls_tls_connect_options_callback we can
// pass any Duplex in to tls.connect instead of a Socket. So we'll use our proxy to keep
// the TLS wrapper and underlying usbmuxd socket separate.
const proxy = new UsbmuxdProxy(usbmuxdSocket);
tlsOptions.socket = proxy;
await new Promise((res, rej) => {
const timeoutId = setTimeout(() => {
rej('The TLS handshake failed to complete after 5s.');
}, 5000);
tls.connect(tlsOptions, function () {
clearTimeout(timeoutId);
// After the handshake, we don't need TLS or the proxy anymore,
// since we'll just pass in the naked usbmuxd socket to the service client
this.destroy();
res();
});
});
}
else {
tlsOptions.socket = usbmuxdSocket;
usbmuxdSocket = tls.connect(tlsOptions);
}
}
const client = new ServiceType(usbmuxdSocket);
this.connections.push(client.socket);
return client;
}
end() {
for (const socket of this.connections) {
// may already be closed
try {
socket.end();
}
catch (err) {
// ignore
}
}
}
}
exports.ClientManager = ClientManager;
class UsbmuxdProxy extends stream_1.Duplex {
constructor(usbmuxdSock) {
super();
this.usbmuxdSock = usbmuxdSock;
this.usbmuxdSock.on('data', (data) => {
this.push(data);
});
}
_write(chunk, encoding, callback) {
this.usbmuxdSock.write(chunk);
callback();
}
_read(size) {
// Stub so we don't error, since we push everything we get from usbmuxd as it comes in.
// TODO: better way to do this?
}
_destroy() {
this.usbmuxdSock.removeAllListeners();
}
}

373
node_modules/native-run/dist/ios/lib/protocol/afc.js generated vendored Normal file
View file

@ -0,0 +1,373 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AFCProtocolWriter = exports.AFCProtocolReader = exports.AFCProtocolClient = exports.AFCError = exports.AFC_FILE_OPEN_FLAGS = exports.AFC_STATUS = exports.AFC_OPS = exports.AFC_HEADER_SIZE = exports.AFC_MAGIC = void 0;
const Debug = require("debug");
const protocol_1 = require("./protocol");
const debug = Debug('native-run:ios:lib:protocol:afc');
exports.AFC_MAGIC = 'CFA6LPAA';
exports.AFC_HEADER_SIZE = 40;
/**
* AFC Operations
*/
var AFC_OPS;
(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+
/**
* 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+
/**
* FileRefReadWithOffset
*/
AFC_OPS[AFC_OPS["FILE_READ_OFFSET"] = 39] = "FILE_READ_OFFSET";
/**
* FileRefWriteWithOffset
*/
AFC_OPS[AFC_OPS["FILE_WRITE_OFFSET"] = 40] = "FILE_WRITE_OFFSET";
})(AFC_OPS = exports.AFC_OPS || (exports.AFC_OPS = {}));
/**
* Error Codes
*/
var AFC_STATUS;
(function (AFC_STATUS) {
AFC_STATUS[AFC_STATUS["SUCCESS"] = 0] = "SUCCESS";
AFC_STATUS[AFC_STATUS["UNKNOWN_ERROR"] = 1] = "UNKNOWN_ERROR";
AFC_STATUS[AFC_STATUS["OP_HEADER_INVALID"] = 2] = "OP_HEADER_INVALID";
AFC_STATUS[AFC_STATUS["NO_RESOURCES"] = 3] = "NO_RESOURCES";
AFC_STATUS[AFC_STATUS["READ_ERROR"] = 4] = "READ_ERROR";
AFC_STATUS[AFC_STATUS["WRITE_ERROR"] = 5] = "WRITE_ERROR";
AFC_STATUS[AFC_STATUS["UNKNOWN_PACKET_TYPE"] = 6] = "UNKNOWN_PACKET_TYPE";
AFC_STATUS[AFC_STATUS["INVALID_ARG"] = 7] = "INVALID_ARG";
AFC_STATUS[AFC_STATUS["OBJECT_NOT_FOUND"] = 8] = "OBJECT_NOT_FOUND";
AFC_STATUS[AFC_STATUS["OBJECT_IS_DIR"] = 9] = "OBJECT_IS_DIR";
AFC_STATUS[AFC_STATUS["PERM_DENIED"] = 10] = "PERM_DENIED";
AFC_STATUS[AFC_STATUS["SERVICE_NOT_CONNECTED"] = 11] = "SERVICE_NOT_CONNECTED";
AFC_STATUS[AFC_STATUS["OP_TIMEOUT"] = 12] = "OP_TIMEOUT";
AFC_STATUS[AFC_STATUS["TOO_MUCH_DATA"] = 13] = "TOO_MUCH_DATA";
AFC_STATUS[AFC_STATUS["END_OF_DATA"] = 14] = "END_OF_DATA";
AFC_STATUS[AFC_STATUS["OP_NOT_SUPPORTED"] = 15] = "OP_NOT_SUPPORTED";
AFC_STATUS[AFC_STATUS["OBJECT_EXISTS"] = 16] = "OBJECT_EXISTS";
AFC_STATUS[AFC_STATUS["OBJECT_BUSY"] = 17] = "OBJECT_BUSY";
AFC_STATUS[AFC_STATUS["NO_SPACE_LEFT"] = 18] = "NO_SPACE_LEFT";
AFC_STATUS[AFC_STATUS["OP_WOULD_BLOCK"] = 19] = "OP_WOULD_BLOCK";
AFC_STATUS[AFC_STATUS["IO_ERROR"] = 20] = "IO_ERROR";
AFC_STATUS[AFC_STATUS["OP_INTERRUPTED"] = 21] = "OP_INTERRUPTED";
AFC_STATUS[AFC_STATUS["OP_IN_PROGRESS"] = 22] = "OP_IN_PROGRESS";
AFC_STATUS[AFC_STATUS["INTERNAL_ERROR"] = 23] = "INTERNAL_ERROR";
AFC_STATUS[AFC_STATUS["MUX_ERROR"] = 30] = "MUX_ERROR";
AFC_STATUS[AFC_STATUS["NO_MEM"] = 31] = "NO_MEM";
AFC_STATUS[AFC_STATUS["NOT_ENOUGH_DATA"] = 32] = "NOT_ENOUGH_DATA";
AFC_STATUS[AFC_STATUS["DIR_NOT_EMPTY"] = 33] = "DIR_NOT_EMPTY";
AFC_STATUS[AFC_STATUS["FORCE_SIGNED_TYPE"] = -1] = "FORCE_SIGNED_TYPE";
})(AFC_STATUS = exports.AFC_STATUS || (exports.AFC_STATUS = {}));
var AFC_FILE_OPEN_FLAGS;
(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;
}
function isStatusResponse(resp) {
return isAFCResponse(resp) && resp.operation === AFC_OPS.STATUS;
}
function isErrorStatusResponse(resp) {
return isStatusResponse(resp) && resp.data !== AFC_STATUS.SUCCESS;
}
class AFCInternalError extends Error {
constructor(msg, requestId) {
super(msg);
this.requestId = requestId;
}
}
class AFCError extends Error {
constructor(msg, status) {
super(msg);
this.status = status;
}
}
exports.AFCError = AFCError;
class AFCProtocolClient extends protocol_1.ProtocolClient {
constructor(socket) {
super(socket, new protocol_1.ProtocolReaderFactory(AFCProtocolReader), new AFCProtocolWriter());
this.requestId = 0;
this.requestCallbacks = {};
const reader = this.readerFactory.create((resp, err) => {
if (err && err instanceof AFCInternalError) {
this.requestCallbacks[err.requestId](resp, err);
}
else if (isErrorStatusResponse(resp)) {
this.requestCallbacks[resp.id](resp, new AFCError(AFC_STATUS[resp.data], resp.data));
}
else {
this.requestCallbacks[resp.id](resp);
}
});
socket.on('data', reader.onData);
}
sendMessage(msg) {
return new Promise((resolve, reject) => {
const requestId = this.requestId++;
this.requestCallbacks[requestId] = async (resp, err) => {
if (err) {
reject(err);
return;
}
if (isAFCResponse(resp)) {
resolve(resp);
}
else {
reject(new Error('Malformed AFC response'));
}
};
this.writer.write(this.socket, { ...msg, requestId });
});
}
}
exports.AFCProtocolClient = AFCProtocolClient;
class AFCProtocolReader extends protocol_1.ProtocolReader {
constructor(callback) {
super(exports.AFC_HEADER_SIZE, callback);
}
parseHeader(data) {
const magic = data.slice(0, 8).toString('ascii');
if (magic !== exports.AFC_MAGIC) {
throw new AFCInternalError(`Invalid AFC packet received (magic != ${exports.AFC_MAGIC})`, data.readUInt32LE(24));
}
// technically these are uint64
this.header = {
magic,
totalLength: data.readUInt32LE(8),
headerLength: data.readUInt32LE(16),
requestId: data.readUInt32LE(24),
operation: data.readUInt32LE(32),
};
debug(`parse header: ${JSON.stringify(this.header)}`);
if (this.header.headerLength < exports.AFC_HEADER_SIZE) {
throw new AFCInternalError('Invalid AFC header', this.header.requestId);
}
return this.header.totalLength - exports.AFC_HEADER_SIZE;
}
parseBody(data) {
const body = {
operation: this.header.operation,
id: this.header.requestId,
data,
};
if (isStatusResponse(body)) {
const status = data.readUInt32LE(0);
debug(`${AFC_OPS[this.header.operation]} response: ${AFC_STATUS[status]}`);
body.data = status;
}
else if (data.length <= 8) {
debug(`${AFC_OPS[this.header.operation]} response: ${Array.prototype.toString.call(body)}`);
}
else {
debug(`${AFC_OPS[this.header.operation]} response length: ${data.length} bytes`);
}
return body;
}
}
exports.AFCProtocolReader = AFCProtocolReader;
class AFCProtocolWriter {
write(socket, msg) {
const { data, payload, operation, requestId } = msg;
const dataLength = data ? data.length : 0;
const payloadLength = payload ? payload.length : 0;
const header = Buffer.alloc(exports.AFC_HEADER_SIZE);
const magic = Buffer.from(exports.AFC_MAGIC);
magic.copy(header);
header.writeUInt32LE(exports.AFC_HEADER_SIZE + dataLength + payloadLength, 8);
header.writeUInt32LE(exports.AFC_HEADER_SIZE + dataLength, 16);
header.writeUInt32LE(requestId, 24);
header.writeUInt32LE(operation, 32);
socket.write(header);
socket.write(data);
if (data.length <= 8) {
debug(`socket write, header: { requestId: ${requestId}, operation: ${AFC_OPS[operation]}}, body: ${Array.prototype.toString.call(data)}`);
}
else {
debug(`socket write, header: { requestId: ${requestId}, operation: ${AFC_OPS[operation]}}, body: ${data.length} bytes`);
}
debug(`socket write, bytes written ${header.length} (header), ${data.length} (body)`);
if (payload) {
socket.write(payload);
}
}
}
exports.AFCProtocolWriter = AFCProtocolWriter;

112
node_modules/native-run/dist/ios/lib/protocol/gdb.js generated vendored Normal file
View file

@ -0,0 +1,112 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GDBProtocolWriter = exports.GDBProtocolReader = exports.GDBProtocolClient = void 0;
const Debug = require("debug");
const protocol_1 = require("./protocol");
const debug = Debug('native-run:ios:lib:protocol:gdb');
const ACK_SUCCESS = '+'.charCodeAt(0);
class GDBProtocolClient extends protocol_1.ProtocolClient {
constructor(socket) {
super(socket, new protocol_1.ProtocolReaderFactory(GDBProtocolReader), new GDBProtocolWriter());
}
}
exports.GDBProtocolClient = GDBProtocolClient;
class GDBProtocolReader extends protocol_1.ProtocolReader {
constructor(callback) {
super(1 /* "Header" is '+' or '-' */, callback);
}
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) {
if (data[0] !== ACK_SUCCESS) {
throw new Error('Unsuccessful debugserver response');
} // TODO: retry?
return -1;
}
parseBody(buffer) {
debug(`Response body: ${buffer.toString()}`);
// check for checksum
const checksum = buffer.slice(-3).toString();
if (checksum.match(/#[0-9a-f]{2}/)) {
// remove '$' prefix and checksum
const msg = buffer.slice(1, -3).toString();
if (validateChecksum(checksum, msg)) {
return msg;
}
else {
throw new Error('Invalid checksum received from debugserver');
}
}
else {
throw new Error("Didn't receive checksum");
}
}
}
exports.GDBProtocolReader = GDBProtocolReader;
class GDBProtocolWriter {
write(socket, msg) {
const { cmd, args } = msg;
debug(`Socket write: ${cmd}, args: ${args}`);
// hex encode and concat all args
const encodedArgs = args
.map((arg) => Buffer.from(arg).toString('hex'))
.join()
.toUpperCase();
const checksumStr = calculateChecksum(cmd + encodedArgs);
const formattedCmd = `$${cmd}${encodedArgs}#${checksumStr}`;
socket.write(formattedCmd);
}
}
exports.GDBProtocolWriter = GDBProtocolWriter;
// hex value of (sum of cmd chars mod 256)
function calculateChecksum(cmdStr) {
let checksum = 0;
for (let i = 0; i < cmdStr.length; i++) {
checksum += cmdStr.charCodeAt(i);
}
let result = (checksum % 256).toString(16);
// pad if necessary
if (result.length === 1) {
result = `0${result}`;
}
return result;
}
function validateChecksum(checksum, msg) {
// remove '#' from checksum
const checksumVal = checksum.slice(1);
// remove '$' from msg and calculate its checksum
const computedChecksum = calculateChecksum(msg);
debug(`Checksum: ${checksumVal}, computed checksum: ${computedChecksum}`);
return checksumVal === computedChecksum;
}

View file

@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./protocol"), exports);
tslib_1.__exportStar(require("./afc"), exports);
tslib_1.__exportStar(require("./gdb"), exports);
tslib_1.__exportStar(require("./lockdown"), exports);
tslib_1.__exportStar(require("./usbmux"), exports);

View file

@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LockdownProtocolWriter = exports.LockdownProtocolReader = exports.LockdownProtocolClient = exports.isLockdownErrorResponse = exports.isLockdownResponse = exports.LOCKDOWN_HEADER_SIZE = void 0;
const Debug = require("debug");
const plist = require("plist");
const lib_errors_1 = require("../lib-errors");
const protocol_1 = require("./protocol");
const debug = Debug('native-run:ios:lib:protocol:lockdown');
exports.LOCKDOWN_HEADER_SIZE = 4;
function isDefined(val) {
return typeof val !== 'undefined';
}
function isLockdownResponse(resp) {
return isDefined(resp.Status);
}
exports.isLockdownResponse = isLockdownResponse;
function isLockdownErrorResponse(resp) {
return isDefined(resp.Error);
}
exports.isLockdownErrorResponse = isLockdownErrorResponse;
class LockdownProtocolClient extends protocol_1.ProtocolClient {
constructor(socket) {
super(socket, new protocol_1.ProtocolReaderFactory(LockdownProtocolReader), new LockdownProtocolWriter());
}
}
exports.LockdownProtocolClient = LockdownProtocolClient;
class LockdownProtocolReader extends protocol_1.PlistProtocolReader {
constructor(callback) {
super(exports.LOCKDOWN_HEADER_SIZE, callback);
}
parseHeader(data) {
return data.readUInt32BE(0);
}
parseBody(data) {
const resp = super.parseBody(data);
debug(`Response: ${JSON.stringify(resp)}`);
if (isLockdownErrorResponse(resp)) {
if (resp.Error === 'DeviceLocked') {
throw new lib_errors_1.IOSLibError('Device is currently locked.', 'DeviceLocked');
}
throw new Error(resp.Error);
}
return resp;
}
}
exports.LockdownProtocolReader = LockdownProtocolReader;
class LockdownProtocolWriter {
write(socket, plistData) {
debug(`socket write: ${JSON.stringify(plistData)}`);
const plistMessage = plist.build(plistData);
const header = Buffer.alloc(exports.LOCKDOWN_HEADER_SIZE);
header.writeUInt32BE(plistMessage.length, 0);
socket.write(header);
socket.write(plistMessage);
}
}
exports.LockdownProtocolWriter = LockdownProtocolWriter;

View file

@ -0,0 +1,111 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProtocolClient = exports.PlistProtocolReader = exports.ProtocolReader = exports.ProtocolReaderFactory = void 0;
const bplistParser = require("bplist-parser");
const plist = require("plist");
const BPLIST_MAGIC = Buffer.from('bplist00');
class ProtocolReaderFactory {
constructor(ProtocolReader) {
this.ProtocolReader = ProtocolReader;
}
create(callback) {
return new this.ProtocolReader(callback);
}
}
exports.ProtocolReaderFactory = ProtocolReaderFactory;
class ProtocolReader {
constructor(headerSize, callback) {
this.headerSize = headerSize;
this.callback = callback;
this.buffer = Buffer.alloc(0);
this.onData = this.onData.bind(this);
}
onData(data) {
try {
// if there's data, add it on to existing buffer
this.buffer = data ? Buffer.concat([this.buffer, data]) : this.buffer;
// we haven't gotten the body length from the header yet
if (!this.bodyLength) {
if (this.buffer.length < this.headerSize) {
// partial header, wait for rest
return;
}
this.bodyLength = this.parseHeader(this.buffer);
// move on to body
this.buffer = this.buffer.slice(this.headerSize);
if (!this.buffer.length) {
// only got header, wait for body
return;
}
}
if (this.buffer.length < this.bodyLength) {
// wait for rest of body
return;
}
if (this.bodyLength === -1) {
this.callback(this.parseBody(this.buffer));
this.buffer = Buffer.alloc(0);
}
else {
this.body = this.buffer.slice(0, this.bodyLength);
this.bodyLength -= this.body.length;
if (!this.bodyLength) {
this.callback(this.parseBody(this.body));
}
this.buffer = this.buffer.slice(this.body.length);
// There are multiple messages here, call parse again
if (this.buffer.length) {
this.onData();
}
}
}
catch (err) {
this.callback(null, err);
}
}
}
exports.ProtocolReader = ProtocolReader;
class PlistProtocolReader extends ProtocolReader {
parseBody(body) {
if (BPLIST_MAGIC.compare(body, 0, 8) === 0) {
return bplistParser.parseBuffer(body);
}
else {
return plist.parse(body.toString('utf8'));
}
}
}
exports.PlistProtocolReader = PlistProtocolReader;
class ProtocolClient {
constructor(socket, readerFactory, writer) {
this.socket = socket;
this.readerFactory = readerFactory;
this.writer = writer;
}
sendMessage(msg, callback) {
return new Promise((resolve, reject) => {
const reader = this.readerFactory.create(async (resp, err) => {
if (err) {
reject(err);
return;
}
if (callback) {
callback(resp, (value) => {
this.socket.removeListener('data', reader.onData);
resolve(value);
}, reject);
}
else {
this.socket.removeListener('data', reader.onData);
resolve(resp);
}
});
this.socket.on('error', (err) => {
throw err;
});
this.socket.on('data', reader.onData);
this.writer.write(this.socket, msg);
});
}
}
exports.ProtocolClient = ProtocolClient;

View file

@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UsbmuxProtocolWriter = exports.UsbmuxProtocolReader = exports.UsbmuxProtocolClient = exports.USBMUXD_HEADER_SIZE = void 0;
const Debug = require("debug");
const plist = require("plist");
const protocol_1 = require("./protocol");
const debug = Debug('native-run:ios:lib:protocol:usbmux');
exports.USBMUXD_HEADER_SIZE = 16;
class UsbmuxProtocolClient extends protocol_1.ProtocolClient {
constructor(socket) {
super(socket, new protocol_1.ProtocolReaderFactory(UsbmuxProtocolReader), new UsbmuxProtocolWriter());
}
}
exports.UsbmuxProtocolClient = UsbmuxProtocolClient;
class UsbmuxProtocolReader extends protocol_1.PlistProtocolReader {
constructor(callback) {
super(exports.USBMUXD_HEADER_SIZE, callback);
}
parseHeader(data) {
return data.readUInt32LE(0) - exports.USBMUXD_HEADER_SIZE;
}
parseBody(data) {
const resp = super.parseBody(data);
debug(`Response: ${JSON.stringify(resp)}`);
return resp;
}
}
exports.UsbmuxProtocolReader = UsbmuxProtocolReader;
class UsbmuxProtocolWriter {
constructor() {
this.useTag = 0;
}
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,
...extraFields,
});
const dataSize = plistMessage ? plistMessage.length : 0;
const protocolVersion = 1;
const messageCode = 8;
const header = Buffer.alloc(exports.USBMUXD_HEADER_SIZE);
header.writeUInt32LE(exports.USBMUXD_HEADER_SIZE + dataSize, 0);
header.writeUInt32LE(protocolVersion, 4);
header.writeUInt32LE(messageCode, 8);
header.writeUInt32LE(this.useTag++, 12); // TODO
socket.write(header);
socket.write(plistMessage);
}
}
exports.UsbmuxProtocolWriter = UsbmuxProtocolWriter;

55
node_modules/native-run/dist/ios/list.js generated vendored Normal file
View file

@ -0,0 +1,55 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.list = exports.run = void 0;
const list_1 = require("../utils/list");
const device_1 = require("./utils/device");
const simulator_1 = require("./utils/simulator");
async function run(args) {
const targets = await list(args);
process.stdout.write(`\n${(0, list_1.formatTargets)(args, targets)}\n`);
}
exports.run = run;
async function list(args) {
const errors = [];
const [devices, virtualDevices] = await Promise.all([
(async () => {
try {
const devices = await (0, device_1.getConnectedDevices)();
return devices.map(deviceToTarget);
}
catch (e) {
errors.push(e);
return [];
}
})(),
(async () => {
try {
const simulators = await (0, simulator_1.getSimulators)();
return simulators.map(simulatorToTarget);
}
catch (e) {
errors.push(e);
return [];
}
})(),
]);
return { devices, virtualDevices, errors };
}
exports.list = list;
function deviceToTarget(device) {
return {
platform: 'ios',
name: device.DeviceName,
model: device.ProductType,
sdkVersion: device.ProductVersion,
id: device.UniqueDeviceID,
};
}
function simulatorToTarget(simulator) {
return {
platform: 'ios',
name: simulator.name,
sdkVersion: simulator.runtime.version,
id: simulator.udid,
};
}

116
node_modules/native-run/dist/ios/run.js generated vendored Normal file
View file

@ -0,0 +1,116 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const Debug = require("debug");
const fs_1 = require("fs");
const path = require("path");
const errors_1 = require("../errors");
const cli_1 = require("../utils/cli");
const process_1 = require("../utils/process");
const lib_errors_1 = require("./lib/lib-errors");
const app_1 = require("./utils/app");
const device_1 = require("./utils/device");
const simulator_1 = require("./utils/simulator");
const debug = Debug('native-run:ios:run');
async function runIpaOrAppFile({ udid, devices, simulators, appPath, bundleId, waitForApp, preferSimulator, }) {
if (udid) {
if (devices.find((d) => d.UniqueDeviceID === udid)) {
await (0, device_1.runOnDevice)(udid, appPath, bundleId, waitForApp);
}
else if (simulators.find((s) => s.udid === udid)) {
await (0, simulator_1.runOnSimulator)(udid, appPath, bundleId, waitForApp);
}
else {
throw new errors_1.IOSRunException(`No device or simulator with UDID "${udid}" found`, errors_1.ERR_TARGET_NOT_FOUND);
}
}
else if (devices.length && !preferSimulator) {
// no udid, use first connected device
await (0, device_1.runOnDevice)(devices[0].UniqueDeviceID, appPath, bundleId, waitForApp);
}
else {
// use default sim
await (0, simulator_1.runOnSimulator)(simulators[simulators.length - 1].udid, appPath, bundleId, waitForApp);
}
}
async function runIpaOrAppFileOnInterval(config) {
const maxRetryCount = 12; // 1 minute
const retryInterval = 5000; // 5 seconds
let error;
let retryCount = 0;
const retry = async () => {
process.stderr.write('Please unlock your device. Waiting 5 seconds...\n');
retryCount++;
await (0, process_1.wait)(retryInterval);
await run();
};
const run = async () => {
try {
await runIpaOrAppFile(config);
}
catch (err) {
if (err instanceof lib_errors_1.IOSLibError && err.code == 'DeviceLocked' && retryCount < maxRetryCount) {
await retry();
}
else {
if (retryCount >= maxRetryCount) {
error = new errors_1.IOSRunException(`Device still locked after 1 minute. Aborting.`, errors_1.ERR_DEVICE_LOCKED);
}
else {
error = err;
}
}
}
};
await run();
if (error) {
throw error;
}
}
async function run(args) {
let appPath = (0, cli_1.getOptionValue)(args, '--app');
if (!appPath) {
throw new errors_1.CLIException('--app is required', errors_1.ERR_BAD_INPUT);
}
const udid = (0, cli_1.getOptionValue)(args, '--target');
const preferSimulator = args.includes('--virtual');
const waitForApp = args.includes('--connect');
const isIPA = appPath.endsWith('.ipa');
if (!(0, fs_1.existsSync)(appPath)) {
throw new errors_1.IOSRunException(`Path '${appPath}' not found`);
}
try {
if (isIPA) {
const { tmpdir } = await Promise.resolve().then(() => require('os'));
const tempDir = (0, fs_1.mkdtempSync)(`${tmpdir()}${path.sep}`);
debug(`Unzipping .ipa to ${tempDir}`);
const appDir = await (0, app_1.unzipIPA)(appPath, tempDir);
appPath = path.join(tempDir, appDir);
}
const bundleId = await (0, app_1.getBundleId)(appPath);
const [devices, simulators] = await Promise.all([(0, device_1.getConnectedDevices)(), (0, simulator_1.getSimulators)()]);
// try to run on device or simulator with udid
const config = {
udid,
devices,
simulators,
appPath,
bundleId,
waitForApp,
preferSimulator,
};
await runIpaOrAppFileOnInterval(config);
}
finally {
if (isIPA) {
try {
await (0, utils_fs_1.remove)(appPath);
}
catch {
// ignore
}
}
}
}
exports.run = run;

60
node_modules/native-run/dist/ios/utils/app.js generated vendored Normal file
View file

@ -0,0 +1,60 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.unzipIPA = exports.getBundleId = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const Debug = require("debug");
const fs_1 = require("fs");
const path = require("path");
const errors_1 = require("../../errors");
const process_1 = require("../../utils/process");
const unzip_1 = require("../../utils/unzip");
const debug = Debug('native-run:ios:utils:app');
// TODO: cross platform? Use plist/bplist
async function getBundleId(appPath) {
const plistPath = path.resolve(appPath, 'Info.plist');
try {
const { stdout } = await (0, process_1.execFile)('/usr/libexec/PlistBuddy', ['-c', 'Print :CFBundleIdentifier', plistPath], {
encoding: 'utf8',
});
if (stdout) {
return stdout.trim();
}
}
catch {
// ignore
}
throw new errors_1.Exception('Unable to get app bundle identifier');
}
exports.getBundleId = getBundleId;
async function unzipIPA(ipaPath, destPath) {
let error;
let appPath = '';
await (0, unzip_1.unzip)(ipaPath, async (entry, zipfile, openReadStream) => {
debug(`Unzip: ${entry.fileName}`);
const dest = path.join(destPath, entry.fileName);
if (entry.fileName.endsWith('/')) {
await (0, utils_fs_1.mkdirp)(dest);
if (entry.fileName.endsWith('.app/')) {
appPath = entry.fileName;
}
zipfile.readEntry();
}
else {
await (0, utils_fs_1.mkdirp)(path.dirname(dest));
const readStream = await openReadStream(entry);
readStream.on('error', (err) => (error = err));
readStream.on('end', () => {
zipfile.readEntry();
});
readStream.pipe((0, fs_1.createWriteStream)(dest));
}
});
if (error) {
throw error;
}
if (!appPath) {
throw new errors_1.Exception('Unable to determine .app directory from .ipa');
}
return appPath;
}
exports.unzipIPA = unzipIPA;

141
node_modules/native-run/dist/ios/utils/device.js generated vendored Normal file
View file

@ -0,0 +1,141 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runOnDevice = exports.getConnectedDevices = void 0;
const child_process_1 = require("child_process");
const Debug = require("debug");
const fs_1 = require("fs");
const path = require("path");
const errors_1 = require("../../errors");
const process_1 = require("../../utils/process");
const lib_1 = require("../lib");
const xcode_1 = require("./xcode");
const debug = Debug('native-run:ios:utils:device');
async function getConnectedDevices() {
const usbmuxClient = new lib_1.UsbmuxdClient(lib_1.UsbmuxdClient.connectUsbmuxdSocket());
const usbmuxDevices = await usbmuxClient.getDevices();
usbmuxClient.socket.end();
return Promise.all(usbmuxDevices.map(async (d) => {
const socket = await new lib_1.UsbmuxdClient(lib_1.UsbmuxdClient.connectUsbmuxdSocket()).connect(d, 62078);
const device = await new lib_1.LockdowndClient(socket).getAllValues();
socket.end();
// For network-connected devices, UniqueDeviceID may not be present in lockdownd response
// Use SerialNumber from usbmuxd device info as fallback (they are the same value)
if (!device.UniqueDeviceID && d.Properties && d.Properties.SerialNumber) {
device.UniqueDeviceID = d.Properties.SerialNumber;
debug(`Using SerialNumber as UniqueDeviceID for network device: ${device.UniqueDeviceID}`);
}
return device;
}));
}
exports.getConnectedDevices = getConnectedDevices;
async function runOnDevice(udid, appPath, bundleId, waitForApp) {
const clientManager = await lib_1.ClientManager.create(udid);
try {
await mountDeveloperDiskImage(clientManager);
const packageName = path.basename(appPath);
const destPackagePath = path.join('PublicStaging', packageName);
await uploadApp(clientManager, appPath, destPackagePath);
const installer = await clientManager.getInstallationProxyClient();
await installer.installApp(destPackagePath, bundleId);
const { [bundleId]: appInfo } = await installer.lookupApp([bundleId]);
// launch fails with EBusy or ENotFound if you try to launch immediately after install
await (0, process_1.wait)(200);
try {
const debugServerClient = await launchApp(clientManager, appInfo);
if (waitForApp) {
(0, process_1.onBeforeExit)(async () => {
// causes continue() to return
debugServerClient.halt();
// give continue() time to return response
await (0, process_1.wait)(64);
});
debug(`Waiting for app to close...\n`);
const result = await debugServerClient.continue();
// TODO: I have no idea what this packet means yet (successful close?)
// if not a close (ie, most likely due to halt from onBeforeExit), then kill the app
if (result !== 'W00') {
await debugServerClient.kill();
}
}
}
catch {
// if launching app throws, try with devicectl, but requires Xcode 15
const [xcodeVersion] = (0, xcode_1.getXcodeVersionInfo)();
const xcodeMajorVersion = Number(xcodeVersion.split('.')[0]);
if (xcodeMajorVersion >= 15) {
const launchResult = (0, child_process_1.spawn)('xcrun', ['devicectl', 'device', 'process', 'launch', '--device', udid, bundleId]);
return new Promise((resolve, reject) => {
launchResult.on('close', (code) => {
if (code === 0) {
resolve();
}
else {
reject(new errors_1.Exception(`There was an error launching app on device`));
}
});
launchResult.on('error', (err) => {
reject(err);
});
});
}
else {
throw new errors_1.Exception(`running on iOS 17 devices requires Xcode 15 and later`);
}
}
}
finally {
clientManager.end();
}
}
exports.runOnDevice = runOnDevice;
async function mountDeveloperDiskImage(clientManager) {
const imageMounter = await clientManager.getMobileImageMounterClient();
// Check if already mounted. If not, mount.
if (!(await imageMounter.lookupImage()).ImageSignature) {
// verify DeveloperDiskImage exists (TODO: how does this work on Windows/Linux?)
// TODO: if windows/linux, download?
const version = await (await clientManager.getLockdowndClient()).getValue('ProductVersion');
const developerDiskImagePath = await (0, xcode_1.getDeveloperDiskImagePath)(version);
const developerDiskImageSig = (0, fs_1.readFileSync)(`${developerDiskImagePath}.signature`);
await imageMounter.uploadImage(developerDiskImagePath, developerDiskImageSig);
await imageMounter.mountImage(developerDiskImagePath, developerDiskImageSig);
}
}
async function uploadApp(clientManager, srcPath, destinationPath) {
const afcClient = await clientManager.getAFCClient();
try {
await afcClient.getFileInfo('PublicStaging');
}
catch (err) {
if (err instanceof lib_1.AFCError && err.status === lib_1.AFC_STATUS.OBJECT_NOT_FOUND) {
await afcClient.makeDirectory('PublicStaging');
}
else {
throw err;
}
}
await afcClient.uploadDirectory(srcPath, destinationPath);
}
async function launchApp(clientManager, appInfo) {
let tries = 0;
while (tries < 3) {
const debugServerClient = await clientManager.getDebugserverClient();
await debugServerClient.setMaxPacketSize(1024);
await debugServerClient.setWorkingDir(appInfo.Container);
await debugServerClient.launchApp(appInfo.Path, appInfo.CFBundleExecutable);
const result = await debugServerClient.checkLaunchSuccess();
if (result === 'OK') {
return debugServerClient;
}
else if (result === 'EBusy' || result === 'ENotFound') {
debug('Device busy or app not found, trying to launch again in .5s...');
tries++;
debugServerClient.socket.end();
await (0, process_1.wait)(500);
}
else {
throw new errors_1.Exception(`There was an error launching app: ${result}`);
}
}
throw new errors_1.Exception('Unable to launch app, number of tries exceeded');
}

90
node_modules/native-run/dist/ios/utils/simulator.js generated vendored Normal file
View file

@ -0,0 +1,90 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runOnSimulator = exports.getSimulators = void 0;
const child_process_1 = require("child_process"); // TODO: need cross-spawn for windows?
const Debug = require("debug");
const errors_1 = require("../../errors");
const log_1 = require("../../utils/log");
const process_1 = require("../../utils/process");
const xcode_1 = require("./xcode");
const debug = Debug('native-run:ios:utils:simulator');
async function getSimulators() {
const simctl = (0, child_process_1.spawnSync)('xcrun', ['simctl', 'list', '--json'], {
encoding: 'utf8',
});
if (simctl.status) {
throw new errors_1.Exception(`Unable to retrieve simulator list: ${simctl.stderr}`);
}
try {
const output = JSON.parse(simctl.stdout);
return output.runtimes
.filter((runtime) => runtime.name.indexOf('watch') === -1 && runtime.name.indexOf('tv') === -1)
.map((runtime) => (output.devices[runtime.identifier] || output.devices[runtime.name])
.filter((device) => device.isAvailable)
.map((device) => ({ ...device, runtime })))
.reduce((prev, next) => prev.concat(next)) // flatten
.sort((a, b) => (a.name < b.name ? -1 : 1));
}
catch (err) {
throw new errors_1.Exception(`Unable to retrieve simulator list: ${err.message}`);
}
}
exports.getSimulators = getSimulators;
async function runOnSimulator(udid, appPath, bundleId, waitForApp) {
debug(`Booting simulator ${udid}`);
const bootResult = (0, 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')) {
throw new errors_1.Exception(`There was an error booting simulator: ${bootResult.stderr}`);
}
debug(`Installing ${appPath} on ${udid}`);
const installResult = (0, child_process_1.spawnSync)('xcrun', ['simctl', 'install', udid, appPath], { encoding: 'utf8' });
if (installResult.status) {
throw new errors_1.Exception(`There was an error installing app on simulator: ${installResult.stderr}`);
}
const xCodePath = await (0, xcode_1.getXCodePath)();
debug(`Running simulator ${udid}`);
const openResult = (0, child_process_1.spawnSync)('open', [`${xCodePath}/Applications/Simulator.app`, '--args', '-CurrentDeviceUDID', udid], { encoding: 'utf8' });
if (openResult.status) {
throw new errors_1.Exception(`There was an error opening simulator: ${openResult.stderr}`);
}
debug(`Launching ${appPath} on ${udid}`);
const launchResult = (0, child_process_1.spawnSync)('xcrun', ['simctl', 'launch', udid, bundleId], { encoding: 'utf8' });
if (launchResult.status) {
throw new errors_1.Exception(`There was an error launching app on simulator: ${launchResult.stderr}`);
}
if (waitForApp) {
(0, process_1.onBeforeExit)(async () => {
const terminateResult = (0, child_process_1.spawnSync)('xcrun', ['simctl', 'terminate', udid, bundleId], { encoding: 'utf8' });
if (terminateResult.status) {
debug('Unable to terminate app on simulator');
}
});
(0, log_1.log)(`Waiting for app to close...\n`);
await waitForSimulatorClose(udid, bundleId);
}
}
exports.runOnSimulator = runOnSimulator;
async function waitForSimulatorClose(udid, bundleId) {
return new Promise((resolve) => {
// poll service list for bundle id
const interval = setInterval(async () => {
try {
const data = (0, child_process_1.spawnSync)('xcrun', ['simctl', 'spawn', udid, 'launchctl', 'list'], { encoding: 'utf8' });
// if bundle id isn't in list, app isn't running
if (data.stdout.indexOf(bundleId) === -1) {
clearInterval(interval);
resolve();
}
}
catch (e) {
debug('Error received from launchctl: %O', e);
debug('App %s no longer found in process list for %s', bundleId, udid);
clearInterval(interval);
resolve();
}
}, 500);
});
}

54
node_modules/native-run/dist/ios/utils/xcode.js generated vendored Normal file
View file

@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDeveloperDiskImagePath = exports.getXCodePath = exports.getXcodeVersionInfo = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const child_process_1 = require("child_process");
const errors_1 = require("../../errors");
const process_1 = require("../../utils/process");
function getXcodeVersionInfo() {
const xcodeVersionInfo = (0, child_process_1.spawnSync)('xcodebuild', ['-version'], {
encoding: 'utf8',
});
if (xcodeVersionInfo.error) {
throw xcodeVersionInfo.error;
}
try {
const trimmed = xcodeVersionInfo.stdout.trim().split('\n');
return ['Xcode ', 'Build version'].map((s, i) => trimmed[i].replace(s, ''));
}
catch (error) {
throw new errors_1.Exception(`There was an error trying to retrieve the Xcode version: ${xcodeVersionInfo.stderr}`);
}
}
exports.getXcodeVersionInfo = getXcodeVersionInfo;
async function getXCodePath() {
try {
const { stdout } = await (0, process_1.execFile)('xcode-select', ['-p'], {
encoding: 'utf8',
});
if (stdout) {
return stdout.trim();
}
}
catch {
// ignore
}
throw new errors_1.Exception('Unable to get Xcode location. Is Xcode installed?');
}
exports.getXCodePath = getXCodePath;
async function getDeveloperDiskImagePath(version) {
const xCodePath = await getXCodePath();
const versionDirs = await (0, utils_fs_1.readdir)(`${xCodePath}/Platforms/iPhoneOS.platform/DeviceSupport/`);
const versionPrefix = version.match(/\d+\.\d+/);
if (versionPrefix === null) {
throw new errors_1.Exception(`Invalid iOS version: ${version}`);
}
// Can look like "11.2 (15C107)"
for (const dir of versionDirs) {
if (dir.includes(versionPrefix[0])) {
return `${xCodePath}/Platforms/iPhoneOS.platform/DeviceSupport/${dir}/DeveloperDiskImage.dmg`;
}
}
throw new errors_1.Exception(`Unable to find Developer Disk Image path for SDK ${version}. Do you have the right version of Xcode?`);
}
exports.getDeveloperDiskImagePath = getDeveloperDiskImagePath;

35
node_modules/native-run/dist/list.js generated vendored Normal file
View file

@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = void 0;
const json_1 = require("./utils/json");
const list_1 = require("./utils/list");
async function run(args) {
const [ios, android] = await Promise.all([
(async () => {
const cmd = await Promise.resolve().then(() => require('./ios/list'));
return cmd.list(args);
})(),
(async () => {
const cmd = await Promise.resolve().then(() => require('./android/list'));
return cmd.list(args);
})(),
]);
if (args.includes('--json')) {
process.stdout.write((0, json_1.stringify)({ ios, android }));
}
else {
process.stdout.write(`
iOS
---
${(0, list_1.formatTargets)(args, ios)}
Android
-------
${(0, list_1.formatTargets)(args, android)}
`);
}
}
exports.run = run;

21
node_modules/native-run/dist/utils/cli.js generated vendored Normal file
View file

@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getOptionValues = exports.getOptionValue = void 0;
function getOptionValue(args, arg, defaultValue) {
const i = args.indexOf(arg);
if (i >= 0) {
return args[i + 1];
}
return defaultValue;
}
exports.getOptionValue = getOptionValue;
function getOptionValues(args, arg) {
const returnVal = [];
args.map((entry, idx) => {
if (entry === arg) {
returnVal.push(args[idx + 1]);
}
});
return returnVal;
}
exports.getOptionValues = getOptionValues;

16
node_modules/native-run/dist/utils/fn.js generated vendored Normal file
View file

@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.once = void 0;
function once(fn) {
let called = false;
let r;
const wrapper = (...args) => {
if (!called) {
called = true;
r = fn(...args);
}
return r;
};
return wrapper;
}
exports.once = once;

12
node_modules/native-run/dist/utils/fs.js generated vendored Normal file
View file

@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isDir = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
async function isDir(p) {
const stats = await (0, utils_fs_1.statSafe)(p);
if (stats === null || stats === void 0 ? void 0 : stats.isDirectory()) {
return true;
}
return false;
}
exports.isDir = isDir;

30
node_modules/native-run/dist/utils/ini.js generated vendored Normal file
View file

@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.writeINI = exports.readINI = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const Debug = require("debug");
const util = require("util");
const debug = Debug('native-run:android:utils:ini');
async function readINI(p, guard = (o) => true) {
const ini = await Promise.resolve().then(() => require('ini'));
try {
const contents = await (0, utils_fs_1.readFile)(p, { encoding: 'utf8' });
const config = ini.decode(contents);
if (!guard(config)) {
throw new Error(`Invalid ini configuration file: ${p}\n` +
`The following guard was used: ${guard.toString()}\n` +
`INI config parsed as: ${util.inspect(config)}`);
}
return { __filename: p, ...config };
}
catch (e) {
debug(e);
}
}
exports.readINI = readINI;
async function writeINI(p, o) {
const ini = await Promise.resolve().then(() => require('ini'));
const contents = ini.encode(o);
await (0, utils_fs_1.writeFile)(p, contents, { encoding: 'utf8' });
}
exports.writeINI = writeINI;

7
node_modules/native-run/dist/utils/json.js generated vendored Normal file
View file

@ -0,0 +1,7 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.stringify = void 0;
function stringify(obj) {
return JSON.stringify(obj, (k, v) => (v instanceof RegExp ? v.toString() : v), '\t');
}
exports.stringify = stringify;

69
node_modules/native-run/dist/utils/list.js generated vendored Normal file
View file

@ -0,0 +1,69 @@
"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");
const json_1 = require("./json");
function formatTargets(args, targets) {
const { devices, virtualDevices, errors } = targets;
const virtualOnly = args.includes('--virtual');
const devicesOnly = args.includes('--device');
if (virtualOnly && devicesOnly) {
throw new errors_1.CLIException('Only one of --device or --virtual may be specified', errors_1.ERR_BAD_INPUT);
}
if (args.includes('--json')) {
let result;
if (virtualOnly) {
result = { virtualDevices, errors };
}
else if (devicesOnly) {
result = { devices, errors };
}
else {
result = { devices, virtualDevices, errors };
}
return (0, json_1.stringify)(result);
}
let output = '';
if (errors.length > 0) {
output += `Errors (!):\n\n${errors.map((e) => ` ${(0, errors_1.serializeError)(e)}`)}\n`;
}
if (!virtualOnly) {
output += printTargets('Connected Device', devices);
if (devicesOnly) {
return output;
}
output += '\n';
}
output += printTargets('Virtual Device', virtualDevices);
return output;
}
exports.formatTargets = formatTargets;
function printTargets(name, targets) {
let output = `${name}s:\n\n`;
if (targets.length === 0) {
output += ` No ${name.toLowerCase()}s found\n`;
}
else {
output += formatTargetTable(targets) + '\n';
}
return output;
}
function formatTargetTable(targets) {
const spacer = (0, utils_terminal_1.indent)(2);
return (spacer +
(0, 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 : '?',
];
}

11
node_modules/native-run/dist/utils/log.js generated vendored Normal file
View file

@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.log = void 0;
const json_1 = require("./json");
function log(message) {
if (process.argv.includes('--json')) {
message = (0, json_1.stringify)({ message });
}
process.stdout.write(message);
}
exports.log = log;

15
node_modules/native-run/dist/utils/object.js generated vendored Normal file
View file

@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sort = void 0;
function sort(obj) {
const entries = [...Object.entries(obj)];
entries.sort(([k1], [k2]) => k1.localeCompare(k2));
for (const [key] of entries) {
delete obj[key];
}
for (const [key, value] of entries) {
obj[key] = value;
}
return obj;
}
exports.sort = sort;

34
node_modules/native-run/dist/utils/process.js generated vendored Normal file
View file

@ -0,0 +1,34 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.onBeforeExit = exports.wait = exports.execFile = exports.exec = void 0;
const cp = require("child_process");
const Debug = require("debug");
const util = require("util");
const fn_1 = require("./fn");
const debug = Debug('native-run:utils:process');
exports.exec = util.promisify(cp.exec);
exports.execFile = util.promisify(cp.execFile);
exports.wait = util.promisify(setTimeout);
const exitQueue = [];
function onBeforeExit(fn) {
exitQueue.push(fn);
}
exports.onBeforeExit = onBeforeExit;
const BEFORE_EXIT_SIGNALS = ['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGBREAK'];
const beforeExitHandlerWrapper = (signal) => (0, fn_1.once)(async () => {
debug('onBeforeExit handler: %s received', signal);
debug('onBeforeExit handler: running %s queued functions', exitQueue.length);
for (const [i, fn] of exitQueue.entries()) {
try {
await fn();
}
catch (e) {
debug('Error from function %d in exit queue: %O', i, e);
}
}
debug('onBeforeExit handler: exiting (exit code %s)', process.exitCode ? process.exitCode : 0);
process.exit();
});
for (const signal of BEFORE_EXIT_SIGNALS) {
process.on(signal, beforeExitHandlerWrapper(signal));
}

22
node_modules/native-run/dist/utils/unzip.js generated vendored Normal file
View file

@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.unzip = void 0;
const util_1 = require("util");
async function unzip(srcPath, onEntry) {
const yauzl = await Promise.resolve().then(() => require('yauzl'));
return new Promise((resolve, reject) => {
yauzl.open(srcPath, { lazyEntries: true }, (err, zipfile) => {
if (!zipfile || err) {
return reject(err);
}
const openReadStream = (0, util_1.promisify)(zipfile.openReadStream.bind(zipfile));
zipfile.once('error', reject);
// resolve when either one happens
zipfile.once('close', resolve); // fd of zip closed
zipfile.once('end', resolve); // last entry read
zipfile.on('entry', (entry) => onEntry(entry, zipfile, openReadStream));
zipfile.readEntry();
});
});
}
exports.unzip = unzip;

106
node_modules/native-run/package.json generated vendored Normal file
View file

@ -0,0 +1,106 @@
{
"name": "native-run",
"version": "2.0.3",
"description": "A CLI for running apps on iOS/Android devices and simulators/emulators",
"bin": {
"native-run": "bin/native-run"
},
"scripts": {
"clean": "rm -rf dist",
"build": "npm run clean && tsc",
"watch": "tsc -w",
"test": "jest --maxWorkers=4",
"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",
"publish:testing": "npm version prerelease --preid=testing --no-git-tag-version && npm publish --tag=testing && git stash",
"prepublishOnly": "npm run build"
},
"main": "dist/index.js",
"files": [
"assets",
"bin",
"dist"
],
"engines": {
"node": ">=16.0.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/ionic-team/native-run.git"
},
"dependencies": {
"@ionic/utils-fs": "^3.1.7",
"@ionic/utils-terminal": "^2.3.4",
"bplist-parser": "^0.3.2",
"debug": "^4.3.4",
"elementtree": "^0.1.7",
"ini": "^4.1.1",
"plist": "^3.1.0",
"split2": "^4.2.0",
"through2": "^4.0.2",
"tslib": "^2.6.2",
"yauzl": "^2.10.0"
},
"devDependencies": {
"@ionic/eslint-config": "^0.4.0",
"@ionic/prettier-config": "^4.0.0",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"@types/debug": "^4.1.10",
"@types/elementtree": "^0.1.3",
"@types/ini": "^1.3.32",
"@types/jest": "^26.0.13",
"@types/node": "^16.0.0",
"@types/plist": "^3.0.4",
"@types/split2": "^4.2.2",
"@types/through2": "^2.0.40",
"@types/yauzl": "^2.10.2",
"eslint": "^8.57.0",
"jest": "^26.4.2",
"prettier": "^3.0.3",
"semantic-release": "^19.0.5",
"ts-jest": "^26.3.0",
"typescript": "~4.9.5"
},
"prettier": "@ionic/prettier-config",
"eslintConfig": {
"extends": "@ionic/eslint-config/recommended",
"rules": {
"@typescript-eslint/explicit-module-boundary-types": [
"warn",
{
"allowArgumentsExplicitlyTypedAsAny": true
}
]
}
},
"release": {
"branches": "stable",
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/github",
"@semantic-release/git"
]
},
"keywords": [
"android",
"ios",
"cli",
"mobile",
"app",
"hybrid",
"native"
],
"author": "Ionic Team <hi@ionicframework.com> (https://ionicframework.com)",
"license": "MIT",
"bugs": {
"url": "https://github.com/ionic-team/native-run/issues"
},
"homepage": "https://github.com/ionic-team/native-run#readme"
}