@u4/adbkit
Version:
A Typescript client for the Android Debug Bridge.
150 lines • 5.31 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const parser_1 = __importDefault(require("./parser"));
const auth_1 = __importDefault(require("./auth"));
const stream_1 = require("stream");
const debug_1 = __importDefault(require("debug"));
class Utils {
/**
* Takes a [`Stream`][node-stream] and reads everything it outputs until the stream ends. Then it resolves with the collected output. Convenient with `client.shell()`.
*
* @param stream The [`Stream`][node-stream] to read.
* @returns All the output as a [`Buffer`][node-buffer]. Use `output.toString('utf-8')` to get a readable string from it.
*/
static readAll(stream) {
return new parser_1.default(stream).readAll();
}
/**
* Parses an Android-formatted mincrypt public key (e.g. `~/.android/adbkey.pub`).
*
* @param keyString The key String or [`Buffer`][node-buffer] to parse. Not a filename.
* @returns The key as a [forge.pki](https://github.com/digitalbazaar/forge#rsa) public key. You may need [node-forge](https://github.com/digitalbazaar/forge) for complicated operations.
*/
static parsePublicKey(keyString) {
return auth_1.default.parsePublicKey(keyString);
}
/**
* A delay promise
*
* @param ms time to wait im ms
* @returns void
*/
static delay(ms) {
let timeout = null;
const promise = new Promise((resolve) => {
timeout = setTimeout(() => {
timeout = null;
resolve();
}, ms);
});
promise.cancel = () => { if (timeout)
clearTimeout(timeout); timeout = null; };
return promise;
}
/**
* Promise waiter for a Duplex to be readable
*
* @param duplex a vanilla Duplex of a PromiseDuplex
* @param timeout do not wait more than timeout
* @returns is the true is duplex is readable
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
static async waitforReadable(duplex, timeout = 0, _debugCtxt = '') {
// let t0 = Date.now();
/**
* prechecks
*/
if (!duplex)
throw Error('can not waitforReadable on a null / undefined duplex');
const stream = (duplex instanceof stream_1.Duplex || duplex instanceof stream_1.Readable) ? duplex : duplex.stream;
if (stream.closed)
throw Error('can not waitforReadable on a closed duplex');
// short-cut
if (stream.readableLength > 0)
return true;
/**
* readable is true by default
*/
let readable = true;
/**
* handle close event
*/
let onClose = () => { };
const waitClose = new Promise((resolveAsClosed) => {
onClose = resolveAsClosed;
stream.on('close', onClose);
});
/**
* Handle readable event
* overwrite theResolve
*/
let theResolve = () => { };
const waitRead = new Promise((resolveAsReadable) => {
theResolve = resolveAsReadable;
stream.on('readable', theResolve);
});
const promises = [waitRead, waitClose];
/**
* Handle timeout event
*/
let timeOut = null;
if (timeout) {
timeOut = Utils.delay(timeout);
promises.push(timeOut.then(() => { readable = false; }));
}
/**
* single Promise race call
*/
await Promise.race(promises);
/**
* clean unused events
*/
stream.off('readable', theResolve);
stream.off('close', onClose);
if (timeOut)
timeOut.cancel();
// t0 = Date.now() - t0;
// console.log(`waitforReadable return after ${t0}ms`, readable, _debugCtxt);
return readable;
}
/**
* Wait for a spesific text in the Duplex
* all text will be concatened in a single string to dean with segments.
*
* @param duplex
* @param expected regexp to match
* @returns matched text
*/
static async waitforText(duplex, expected, timeout = 10000) {
let allText = '';
const t0 = Date.now();
let nextTimeout = timeout;
for (;;) {
await this.waitforReadable(duplex, timeout);
const buf = await duplex.read();
if (buf) {
const text = buf.toString();
allText += text;
if (expected.test(allText))
return text;
// console.log('RCV Non matching DATA:', text);
}
if (timeout) {
const timeSpend = Date.now() - t0;
if (nextTimeout <= 0)
throw Error(`timeout waiting for ${expected}, receved: ${allText}`);
nextTimeout = timeout - timeSpend;
}
}
}
static debug(name) {
const debug = (0, debug_1.default)(name);
debug.log = console.log.bind(console);
return debug;
}
}
exports.default = Utils;
//# sourceMappingURL=utils.js.map