Skip to content

Commit

Permalink
feat(android): have --forward accept multiple values (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
mhartington authored and imhoffd committed May 30, 2019
1 parent 998f5e2 commit 7844ea4
Show file tree
Hide file tree
Showing 15 changed files with 124 additions and 85 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@
"ts-jest": "^24.0.2",
"tslint": "^5.12.1",
"tslint-ionic-rules": "0.0.21",
"typescript": "~3.5.1"
"typescript": "~3.5.1",
"typescript-tslint-plugin": "0.3.1"
},
"release": {
"branch": "stable",
Expand Down
2 changes: 1 addition & 1 deletion src/android/help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ const help = `
--forward <port:port> ... Forward a port from device to host
`;

export async function run() {
export async function run(args: ReadonlyArray<string>): Promise<void> {
process.stdout.write(`${help}\n`);
}
19 changes: 11 additions & 8 deletions src/android/index.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
export async function run(args: string[]) {
import { Command } from '../';

export async function run(args: ReadonlyArray<string>): Promise<void> {
let cmd: Command;

if (args.includes('--help') || args.includes('-h')) {
const help = await import('./help');
return help.run();
cmd = await import('./help');
return cmd.run(args);
}

if (args.includes('--list')) {
const list = await import ('./list');
process.stdout.write(await list.run(args));
return;
cmd = await import ('./list');
return cmd.run(args);
}

if (args.includes('--sdk-info')) {
const cmd = await import ('./sdk-info');
cmd = await import ('./sdk-info');
return cmd.run(args);
}

const cmd = await import('./run');
cmd = await import('./run');
await cmd.run(args);
}
10 changes: 7 additions & 3 deletions src/android/list.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { list } from '../utils/list';
import { format } from '../utils/list';

import { getDeviceTargets, getVirtualTargets } from './utils/list';
import { getSDK } from './utils/sdk';

export async function run(args: string[]) {
export async function run(args: ReadonlyArray<string>): Promise<void> {
process.stdout.write(await list(args));
}

export async function list(args: ReadonlyArray<string>): Promise<string> {
const sdk = await getSDK();
const [ devices, virtualDevices ] = await Promise.all([
getDeviceTargets(sdk),
getVirtualTargets(sdk),
]);

return list(args, devices, virtualDevices);
return format(args, devices, virtualDevices);
}
36 changes: 22 additions & 14 deletions src/android/run.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CLIException, ERR_BAD_INPUT, ERR_TARGET_NOT_FOUND, RunException } from '../errors';
import { getOptionValue } from '../utils/cli';
import { getOptionValue, getOptionsValue } from '../utils/cli';
import { log } from '../utils/log';
import { onBeforeExit } from '../utils/process';

Expand All @@ -9,20 +9,24 @@ import { getInstalledAVDs } from './utils/avd';
import { installApkToDevice, selectDeviceByTarget, selectHardwareDevice, selectVirtualDevice } from './utils/run';
import { SDK, getSDK } from './utils/sdk';

export async function run(args: string[]) {
export async function run(args: ReadonlyArray<string>): Promise<void> {
const sdk = await getSDK();
const apkPath = getOptionValue(args, '--app');
const forwardedPorts = getOptionValue(args, '--forward');
let ports: Ports | undefined;

if (forwardedPorts) {
const [ device, host ] = forwardedPorts.split(':');
const forwardedPorts = getOptionsValue(args, '--forward');

if (!device || !host) {
throw new CLIException('Invalid --forward value: expecting <device port:host port>, e.g. 8080:8080');
}
const ports: Ports[] = [];

if (forwardedPorts && forwardedPorts.length > 0) {
forwardedPorts.forEach((port: string) => {
const [ device, host ] = port.split(':');

ports = { device, host };
if (!device || !host) {
throw new CLIException(`Invalid --forward value "${port}": expecting <device port:host port>, e.g. 8080:8080`);
}

ports.push({ device, host });
});
}

if (!apkPath) {
Expand All @@ -37,8 +41,10 @@ export async function run(args: string[]) {
await waitForBoot(sdk, device);

if (ports) {
await forwardPorts(sdk, device, ports);
log(`Forwarded device port ${ports.device} to host port ${ports.host}\n`);
await Promise.all(ports.map(async (port: Ports) => {
await forwardPorts(sdk, device, port);
log(`Forwarded device port ${port.device} to host port ${port.host}\n`);
}));
}

await installApkToDevice(sdk, device, apkPath, appId);
Expand All @@ -50,7 +56,9 @@ export async function run(args: string[]) {

onBeforeExit(async () => {
if (ports) {
await unforwardPorts(sdk, device, ports);
await Promise.all(ports.map(async (port: Ports) => {
await unforwardPorts(sdk, device, port);
}));
}
});

Expand All @@ -64,7 +72,7 @@ export async function run(args: string[]) {
}
}

export async function selectDevice(sdk: SDK, args: string[]): Promise<Device> {
export async function selectDevice(sdk: SDK, args: ReadonlyArray<string>): Promise<Device> {
const devices = await getDevices(sdk);
const avds = await getInstalledAVDs(sdk);

Expand Down
2 changes: 1 addition & 1 deletion src/android/sdk-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface SDKInfo {
tools: SDKPackage[];
}

export async function run(args: string[]) {
export async function run(args: ReadonlyArray<string>): Promise<void> {
const sdk = await getSDK();
const packages = await findAllSDKPackages(sdk);
const apis = await getAPILevels(packages);
Expand Down
2 changes: 1 addition & 1 deletion src/help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ const help = `
`;

export async function run() {
export async function run(args: ReadonlyArray<string>): Promise<void> {
process.stdout.write(help);
}
42 changes: 14 additions & 28 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import { stringify } from './utils/json';

const debug = Debug('native-run');

export async function run() {
export interface Command {
readonly run: (args: ReadonlyArray<string>) => Promise<void>;
}

export async function run(): Promise<void> {
const args = process.argv.slice(2);

if (args.includes('--version')) {
Expand All @@ -15,21 +19,23 @@ export async function run() {
return;
}

let cmd: Command;
const [ platform, ...platformArgs ] = args;

try {
if (platform === 'android') {
const lib = await import('./android');
await lib.run(platformArgs);
cmd = await import('./android');
await cmd.run(platformArgs);
} else if (platform === 'ios') {
const lib = await import('./ios');
await lib.run(platformArgs);
cmd = await import('./ios');
await cmd.run(platformArgs);
} else if (platform === '--list') {
await list(args);
cmd = await import('./list');
await cmd.run(args);
} else {
if (!platform || platform === 'help' || args.includes('--help') || args.includes('-h') || platform.startsWith('-')) {
const help = await import('./help');
return help.run();
cmd = await import('./help');
return cmd.run(args);
}

throw new CLIException(`Unsupported platform: "${platform}"`, ERR_BAD_INPUT);
Expand All @@ -41,26 +47,6 @@ export async function run() {
}
}

async function list(args: string[]) {
const [iosOutput, androidOutput] = await Promise.all([
import('./ios/list').then(iosList => iosList.run(args)),
import('./android/list').then(androidList => androidList.run(args)),
]);

if (!args.includes('--json')) {
process.stdout.write(`iOS\n---\n\n${iosOutput}\n`);
process.stdout.write(`Android\n-------\n\n${androidOutput}`);
} else {
const adjustLines = (output: string) => output.split('\n').map(line => ` ${line}`).join('\n').trim();
process.stdout.write(`
{
"ios": ${adjustLines(iosOutput)},
"android": ${adjustLines(androidOutput)}
}`
);
}
}

function serializeError(e: Error): string {
const stack = String(e.stack ? e.stack : e);

Expand Down
19 changes: 11 additions & 8 deletions src/ios/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
export async function run(args: string[]) {
import { Command } from '../';

export async function run(args: ReadonlyArray<string>): Promise<void> {
let cmd: Command;

if (args.includes('--help') || args.includes('-h')) {
const help = await import('./help');
return help.run();
cmd = await import('./help');
return cmd.run(args);
}

if (args.includes('--list') || args.includes('-l')) {
const list = await import('./list');
process.stdout.write(await list.run(args));
return;
cmd = await import('./list');
return cmd.run(args);
}

const runCmd = await import('./run');
return runCmd.run(args);
cmd = await import('./run');
await cmd.run(args);
}
30 changes: 17 additions & 13 deletions src/ios/list.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
import * as Debug from 'debug';
import { DeviceValues } from 'node-ioslib';

import { Target, list } from '../utils/list';
import { Target, format } from '../utils/list';

import { getConnectedDevices } from './utils/device';
import { Simulator, getSimulators } from './utils/simulator';

const debug = Debug('native-run:ios:list');

export async function run(args: string[]) {
export async function run(args: ReadonlyArray<string>): Promise<void> {
process.stdout.write(await list(args));
}

export async function list(args: ReadonlyArray<string>): Promise<string> {
const devicesPromise = getConnectedDevices()
.then(devices => devices.map(deviceToTarget))
.catch(err => {
debug(`There was an error getting the iOS device list: ${err.message}`);
return [];
});
.then(devices => devices.map(deviceToTarget))
.catch(err => {
debug('There was an error getting the iOS device list: %O', err);
return [];
});

const simulatorsPromise = getSimulators()
.then(simulators => simulators.map(simulatorToTarget))
.catch(err => {
debug(`There was an error getting the iOS simulator list: ${err.message}`);
return [];
});
.then(simulators => simulators.map(simulatorToTarget))
.catch(err => {
debug('There was an error getting the iOS simulator list: %O', err);
return [];
});

const [ devices, simulators ] = await Promise.all([devicesPromise, simulatorsPromise]);

return list(args, devices, simulators);
return format(args, devices, simulators);
}

function deviceToTarget(device: DeviceValues): Target {
Expand Down
2 changes: 1 addition & 1 deletion src/ios/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { getSimulators, runOnSimulator } from './utils/simulator';

const debug = Debug('native-run:ios:run');

export async function run(args: string[]) {
export async function run(args: ReadonlyArray<string>): Promise<void> {
let appPath = getOptionValue(args, '--app');
if (!appPath) {
throw new CLIException('--app is required', ERR_BAD_INPUT);
Expand Down
19 changes: 19 additions & 0 deletions src/list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export async function run(args: ReadonlyArray<string>): Promise<void> {
const [iosOutput, androidOutput] = await Promise.all([
import('./ios/list').then(iosList => iosList.list(args)),
import('./android/list').then(androidList => androidList.list(args)),
]);

if (!args.includes('--json')) {
process.stdout.write(`iOS\n---\n\n${iosOutput}\n`);
process.stdout.write(`Android\n-------\n\n${androidOutput}`);
} else {
const adjustLines = (output: string) => output.split('\n').map(line => `\t${line}`).join('\n').trim();
process.stdout.write(`
{
\t"ios": ${adjustLines(iosOutput)},
\t"android": ${adjustLines(androidOutput)}
}`
);
}
}
16 changes: 13 additions & 3 deletions src/utils/cli.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export function getOptionValue(args: string[], arg: string): string | undefined;
export function getOptionValue(args: string[], arg: string, defaultValue: string): string;
export function getOptionValue(args: string[], arg: string, defaultValue?: string): string | undefined {
export function getOptionValue(args: ReadonlyArray<string>, arg: string): string | undefined;
export function getOptionValue(args: ReadonlyArray<string>, arg: string, defaultValue: string): string;
export function getOptionValue(args: ReadonlyArray<string>, arg: string, defaultValue?: string): string | undefined {
const i = args.indexOf(arg);

if (i >= 0) {
Expand All @@ -9,3 +9,13 @@ export function getOptionValue(args: string[], arg: string, defaultValue?: strin

return defaultValue;
}

export function getOptionsValue(args: ReadonlyArray<string>, arg: string): string[] {
const returnVal: string[] = [];
args.map((entry: string, idx: number) => {
if (entry === arg) {
returnVal.push(args[idx + 1]);
}
});
return returnVal;
}
4 changes: 2 additions & 2 deletions src/utils/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export interface Target {
readonly format: () => string;
}

export function list(args: string[], devices: Target[], virtualDevices: Target[]) {
export function format(args: ReadonlyArray<string>, devices: ReadonlyArray<Target>, virtualDevices: ReadonlyArray<Target>): string {
const virtualOnly = args.includes('--virtual');
const devicesOnly = args.includes('--device');

Expand Down Expand Up @@ -43,7 +43,7 @@ export function list(args: string[], devices: Target[], virtualDevices: Target[]
return output;
}

function printTargets(name: string, targets: Target[]) {
function printTargets(name: string, targets: ReadonlyArray<Target>) {
let output = `${name}s:\n\n`;
if (targets.length === 0) {
output += ` No ${name.toLowerCase()}s found\n`;
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"target": "es2017",
"lib": [
"es2017"
]
],
"plugins": [{ "name": "typescript-tslint-plugin" }]
},
"include": [
"src/**/*"
Expand Down

0 comments on commit 7844ea4

Please sign in to comment.