adbkit typing

Summary: Adding proper types for adbkit (extracted from their documentation)

Reviewed By: passy

Differential Revision: D17342184

fbshipit-source-id: da0fc0264961ca3a0fa775ab5165d20872042eb8
This commit is contained in:
Daniel Büchele
2019-09-13 05:25:36 -07:00
committed by Facebook Github Bot
parent 01be3dc5d1
commit 4e7cf077b8
8 changed files with 144 additions and 168 deletions

View File

@@ -6,14 +6,13 @@
*/ */
import BaseDevice, {DeviceType, DeviceShell, LogLevel} from './BaseDevice'; import BaseDevice, {DeviceType, DeviceShell, LogLevel} from './BaseDevice';
import adb from 'adbkit-fb'; import adb, {Client as ADBClient} from 'adbkit-fb';
import {Priority} from 'adbkit-logcat-fb'; import {Priority} from 'adbkit-logcat-fb';
import child_process from 'child_process'; import child_process from 'child_process';
import {spawn} from 'promisify-child-process'; import {spawn} from 'promisify-child-process';
import ArchivedDevice from './ArchivedDevice'; import ArchivedDevice from './ArchivedDevice';
import {createWriteStream} from 'fs'; import {createWriteStream} from 'fs';
type ADBClient = any;
const DEVICE_RECORDING_DIR = '/sdcard/flipper_recorder'; const DEVICE_RECORDING_DIR = '/sdcard/flipper_recorder';
export default class AndroidDevice extends BaseDevice { export default class AndroidDevice extends BaseDevice {
@@ -26,8 +25,8 @@ export default class AndroidDevice extends BaseDevice {
super(serial, deviceType, title, 'Android'); super(serial, deviceType, title, 'Android');
this.adb = adb; this.adb = adb;
this.icon = 'icons/android.svg'; this.icon = 'icons/android.svg';
this.adb.openLogcat(this.serial).then((reader: any) => { this.adb.openLogcat(this.serial).then(reader => {
reader.on('entry', (entry: any) => { reader.on('entry', entry => {
let type: LogLevel = 'unknown'; let type: LogLevel = 'unknown';
if (entry.priority === Priority.VERBOSE) { if (entry.priority === Priority.VERBOSE) {
type = 'verbose'; type = 'verbose';
@@ -62,7 +61,6 @@ export default class AndroidDevice extends BaseDevice {
adb: ADBClient; adb: ADBClient;
pidAppMapping: {[key: number]: string} = {}; pidAppMapping: {[key: number]: string} = {};
logReader: any;
private recordingDestination?: string; private recordingDestination?: string;
supportedColumns(): Array<string> { supportedColumns(): Array<string> {
@@ -105,7 +103,7 @@ export default class AndroidDevice extends BaseDevice {
screenshot(): Promise<Buffer> { screenshot(): Promise<Buffer> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.adb.screencap(this.serial).then((stream: NodeJS.WriteStream) => { this.adb.screencap(this.serial).then(stream => {
const chunks: Array<Buffer> = []; const chunks: Array<Buffer> = [];
stream stream
.on('data', (chunk: Buffer) => chunks.push(chunk)) .on('data', (chunk: Buffer) => chunks.push(chunk))
@@ -149,9 +147,7 @@ export default class AndroidDevice extends BaseDevice {
.then( .then(
() => () =>
new Promise((resolve, reject) => new Promise((resolve, reject) =>
this.adb this.adb.pull(this.serial, recordingLocation).then(stream => {
.pull(this.serial, recordingLocation)
.then((stream: NodeJS.WriteStream) => {
stream.on('end', resolve); stream.on('end', resolve);
stream.on('error', reject); stream.on('error', reject);
stream.pipe(createWriteStream(destination)); stream.pipe(createWriteStream(destination));

View File

@@ -15,32 +15,25 @@ import {getAdbClient} from '../utils/adbClient';
import {default as which} from 'which'; import {default as which} from 'which';
import {promisify} from 'util'; import {promisify} from 'util';
import {ServerPorts} from '../reducers/application'; import {ServerPorts} from '../reducers/application';
import {EventEmitter} from 'events'; import {Client as ADBClient} from 'adbkit-fb';
function createDevice( function createDevice(
adbClient: any, adbClient: ADBClient,
device: any, device: any,
ports?: ServerPorts, ports?: ServerPorts,
): Promise<AndroidDevice> { ): Promise<AndroidDevice> {
return new Promise((resolve, reject) => { return new Promise(resolve => {
const type = const type =
device.type !== 'device' || device.id.startsWith('emulator') device.type !== 'device' || device.id.startsWith('emulator')
? 'emulator' ? 'emulator'
: 'physical'; : 'physical';
adbClient adbClient.getProperties(device.id).then(async props => {
.getProperties(device.id)
.then(async (props: {[key: string]: string}) => {
let name = props['ro.product.model']; let name = props['ro.product.model'];
if (type === 'emulator') { if (type === 'emulator') {
name = (await getRunningEmulatorName(device.id)) || name; name = (await getRunningEmulatorName(device.id)) || name;
} }
const androidDevice = new AndroidDevice( const androidDevice = new AndroidDevice(device.id, type, name, adbClient);
device.id,
type,
name,
adbClient,
);
if (ports) { if (ports) {
androidDevice.reverse([ports.secure, ports.insecure]); androidDevice.reverse([ports.secure, ports.insecure]);
} }
@@ -51,7 +44,7 @@ function createDevice(
export async function getActiveAndroidDevices(): Promise<Array<BaseDevice>> { export async function getActiveAndroidDevices(): Promise<Array<BaseDevice>> {
const client = await getAdbClient(); const client = await getAdbClient();
const androidDevices: Array<AndroidDevice> = await client.listDevices(); const androidDevices = await client.listDevices();
return await Promise.all( return await Promise.all(
androidDevices.map(device => createDevice(client, device)), androidDevices.map(device => createDevice(client, device)),
); );
@@ -85,7 +78,7 @@ export default (store: Store, logger: Logger) => {
const watchAndroidDevices = () => { const watchAndroidDevices = () => {
// get emulators // get emulators
promisify(which)('emulator') promisify(which)('emulator')
.catch(e => `${process.env.ANDROID_HOME || ''}/tools/emulator`) .catch(() => `${process.env.ANDROID_HOME || ''}/tools/emulator`)
.then(emulatorPath => { .then(emulatorPath => {
child_process.exec( child_process.exec(
`${emulatorPath} -list-avds`, `${emulatorPath} -list-avds`,
@@ -107,7 +100,7 @@ export default (store: Store, logger: Logger) => {
.then(client => { .then(client => {
client client
.trackDevices() .trackDevices()
.then((tracker: EventEmitter) => { .then(tracker => {
tracker.on('error', err => { tracker.on('error', err => {
if (err.message === 'Connection closed') { if (err.message === 'Connection closed') {
// adb server has shutdown, remove all android devices // adb server has shutdown, remove all android devices

View File

@@ -20,6 +20,7 @@ import {reportPlatformFailures} from './metrics';
import {getAdbClient} from './adbClient'; import {getAdbClient} from './adbClient';
import * as androidUtil from './androidContainerUtility'; import * as androidUtil from './androidContainerUtility';
import os from 'os'; import os from 'os';
import {Client as ADBClient} from 'adbkit-fb';
const tmpFile = promisify(tmp.file) as ( const tmpFile = promisify(tmp.file) as (
options?: FileOptions, options?: FileOptions,
@@ -72,7 +73,7 @@ export type SecureServerConfig = {
*/ */
export default class CertificateProvider { export default class CertificateProvider {
logger: Logger; logger: Logger;
adb: Promise<any>; adb: Promise<ADBClient>;
certificateSetup: Promise<void>; certificateSetup: Promise<void>;
server: Server; server: Server;
@@ -260,7 +261,7 @@ export default class CertificateProvider {
): Promise<string> { ): Promise<string> {
return this.adb return this.adb
.then(client => client.listDevices()) .then(client => client.listDevices())
.then((devices: Array<{id: string}>) => { .then(devices => {
if (devices.length === 0) { if (devices.length === 0) {
throw new Error('No Android devices found'); throw new Error('No Android devices found');
} }

View File

@@ -14,7 +14,7 @@ import adbkit, {Client} from 'adbkit-fb';
const MAX_RETRIES = 5; const MAX_RETRIES = 5;
let instance: Promise<Client>; let instance: Promise<Client>;
export function getAdbClient(): Promise<any> { export function getAdbClient(): Promise<Client> {
if (!instance) { if (!instance) {
instance = reportPlatformFailures(createClient(), 'createADBClient'); instance = reportPlatformFailures(createClient(), 'createADBClient');
} }

View File

@@ -12,7 +12,7 @@
*/ */
import {getAdbClient} from './adbClient'; import {getAdbClient} from './adbClient';
import {UnsupportedError} from './metrics'; import {UnsupportedError} from './metrics';
const adbkit = require('adbkit-fb'); import adbkit from 'adbkit-fb';
const allowedAppNameRegex = /^[a-zA-Z0-9._\-]+$/; const allowedAppNameRegex = /^[a-zA-Z0-9._\-]+$/;
const appNotDebuggableRegex = /debuggable/; const appNotDebuggableRegex = /debuggable/;

View File

@@ -14,11 +14,58 @@ interface Util {
readAll: (stream: NodeJS.ReadStream) => Promise<Buffer>; readAll: (stream: NodeJS.ReadStream) => Promise<Buffer>;
} }
// https://github.com/openstf/adbkit#pulltransfer
interface PullTransfer extends NodeJS.WriteStream {
cancel: () => this;
on(
event: 'progress',
listener: (stats: {bytesTransferred: number}) => void,
): this;
on(event: 'error', listener: (err: Error) => void): this;
on(event: 'end', listener: () => void): this;
}
interface DeviceTracker extends NodeJS.EventEmitter {
on(event: 'add', listener: (device: Device) => void): this;
on(event: 'remove', listener: (device: Device) => void): this;
on(event: 'change', listener: (device: Device) => void): this;
on(
event: 'changeSet',
listener: (changes: {
added: Device[];
removed: Device[];
changed: Device[];
}) => void,
): this;
on(event: 'error', listener: (err: Error) => void): this;
on(event: 'end', listener: () => void): this;
}
declare module 'adbkit-fb' { declare module 'adbkit-fb' {
const util: Util; const util: Util;
const adbkit: any; const adbkit: any;
export interface Client { export interface Client {
listDevices: () => Promise<Device[]>; listDevices: () => Promise<Device[]>;
reverse: (
serial: string,
remote: string,
local: string,
) => Promise<boolean>;
shell: (
serial: string,
command: string | string[],
) => Promise<NodeJS.ReadStream>;
screencap: (serial: string) => Promise<NodeJS.WriteStream>;
pull: (serial: string, path: string) => Promise<PullTransfer>;
openLogcat: (
serial: string,
options?: {
clear?: boolean;
},
) => Promise<import('adbkit-logcat-fb').Reader>;
getProperties: (serial: string) => Promise<{[key: string]: string}>;
trackDevices: () => Promise<DeviceTracker>;
kill: () => Promise<boolean>;
} }
export function createClient(config: {port: number; host: string}): Client; export function createClient(config: {port: number; host: string}): Client;
} }

View File

@@ -1,127 +0,0 @@
/**
* Copyright 2018-present Facebook.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* @format
*/
// This module declaration is a stub!
// Please extend this as needed.
declare module 'adbkit-logcat-fb' {
class Reader {
constructor(options: any);
connect(stream: any): any;
end(): any;
exclude(tag: any): any;
excludeAll(): any;
include(tag: any, priority: any): any;
includeAll(priority: any): any;
resetFilters(): any;
static ANY: string;
static defaultMaxListeners: number;
static init(): void;
static listenerCount(emitter: any, type: any): any;
static once(emitter: any, name: any): any;
static usingDomains: boolean;
}
function Priority(): void;
function readStream(stream: any, options: any): any;
namespace Priority {
const DEBUG: number;
const DEFAULT: number;
const ERROR: number;
const FATAL: number;
const INFO: number;
const SILENT: number;
const UNKNOWN: number;
const VERBOSE: number;
const WARN: number;
function fromLetter(letter: any): any;
function fromName(name: any): any;
function toLetter(value: any): any;
function toName(value: any): any;
}
namespace Reader {
class EventEmitter {
constructor();
addListener(type: any, listener: any): any;
emit(type: any, args: any): any;
eventNames(): any;
getMaxListeners(): any;
listenerCount(type: any): any;
listeners(type: any): any;
off(type: any, listener: any): any;
on(type: any, listener: any): any;
once(type: any, listener: any): any;
prependListener(type: any, listener: any): any;
prependOnceListener(type: any, listener: any): any;
rawListeners(type: any): any;
removeAllListeners(type: any, ...args: any[]): any;
removeListener(type: any, listener: any): any;
setMaxListeners(n: any): any;
static EventEmitter: any;
static defaultMaxListeners: number;
static init(): void;
static listenerCount(emitter: any, type: any): any;
static once(emitter: any, name: any): any;
static usingDomains: boolean;
}
}
}

View File

@@ -0,0 +1,66 @@
/**
* Copyright 2018-present Facebook.
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* @format
*/
// This module declaration is a stub!
// Please extend this as needed.
declare module 'adbkit-logcat-fb' {
type PriorityValue = number;
interface Reader extends NodeJS.EventEmitter {
connect(stream: NodeJS.WriteStream): this;
end(): this;
exclude(tag: string): this;
excludeAll(): this;
include(tag: string, priority?: PriorityValue): this;
includeAll(priority?: PriorityValue): this;
resetFilters(): this;
on(event: 'error', listener: (err: Error) => void): this;
on(event: 'end', listener: () => void): this;
on(event: 'finish', listener: () => void): this;
on(event: 'entry', listener: (entry: Entry) => void): this;
}
interface Entry {
date: Date;
pid: number;
tid: number;
priority: PriorityValue;
tag: string;
message: string;
toBinary(): Buffer;
}
interface Priority {
DEBUG: PriorityValue;
DEFAULT: PriorityValue;
ERROR: PriorityValue;
FATAL: PriorityValue;
INFO: PriorityValue;
SILENT: PriorityValue;
UNKNOWN: PriorityValue;
VERBOSE: PriorityValue;
WARN: PriorityValue;
fromLetter(letter: string): PriorityValue | undefined;
fromName(name: string): PriorityValue | undefined;
toLetter(value: PriorityValue): string;
toName(value: PriorityValue): string;
}
function readStream(
stream: NodeJS.WriteStream,
options?: {
format: 'binary';
fixLineFeeds: boolean;
},
): Reader;
const Priority: Priority;
const Reader: Reader;
}