Skip to content
This repository was archived by the owner on Feb 2, 2021. It is now read-only.

chore: merge release in master #1044

Merged
merged 14 commits into from
Jan 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1575,6 +1575,38 @@ interface IProgressIndicator {
* @return {Promise<T>}
*/
showProgressIndicator<T>(promise: Promise<T>, timeout: number, options?: { surpressTrailingNewLine?: boolean }): Promise<T>;

/**
* Returns a spinner instance that will print a specified message when spinner is started and will repeat it until spinner is stopped.
* In case the terminal is not interactive, a mocked instance is returned, so the spinner will print the required message a single time - when it is started.
* @param {string} message The message to be printed.
* @returns {ISpinner} Instance of clui.Spinner in case terminal is interactive, mocked instance otherwise.
*/
getSpinner(message: string): ISpinner;
}

/**
* Describes the clui spinner.
*/
interface ISpinner {
/**
* Sets the message that will be printed by spinner.
* @param {string} msg The new message.
* @returns {void}
*/
message(msg: string): void;

/**
* Starts the spinner.
* @returns {void}
*/
start(): void;

/**
* Stops the spinner.
* @returns {void}
*/
stop(): void;
}

/**
Expand Down Expand Up @@ -1715,6 +1747,25 @@ interface IVersionData {
patch: string;
}

interface IWaitForPortListenData {
/**
* Port to be checked.
* @type {number}
*/
port: number;

/**
* Max amount of time in milliseconds to wait.
* @type {number}
*/
timeout: number;
/**
* @optional The amount of time between each check.
* @type {number}
*/
interval?: number;
}

/**
* Wrapper for net module of Node.js.
*/
Expand All @@ -1740,6 +1791,13 @@ interface INet {
* @return {Promise<boolean>} true if the port is available.
*/
isPortAvailable(port: number): Promise<boolean>;

/**
* Waits for port to be in LISTEN state.
* @param {IWaitForPortListenData} waitForPortListenData Data describing port, timeout and interval.
* @returns {boolean} true in case port is in LISTEN state, false otherwise.
*/
waitForPortToListen(waitForPortListenData: IWaitForPortListenData): Promise<boolean>;
}

interface IProcessService {
Expand Down Expand Up @@ -1929,6 +1987,12 @@ interface IOsInfo {
* @return {string} A string identifying the operating system bitness.
*/
arch(): string;

/**
* Returns a string identifying the operating system platform.
* @return {string} A string identifying the operating system platform.
*/
platform(): string;
}

interface IPromiseActions<T> {
Expand Down
26 changes: 26 additions & 0 deletions definitions/mobile.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -580,8 +580,34 @@ declare module Mobile {
iOSSimPath: string;
}

/**
* Describes the information when trying to connect to port.
*/
interface IConnectToPortData {
/**
* The port to connect.
* @type {number}
*/
port: number;

/**
* Timeout in milliseconds.
* @type {number}
*/
timeout?: number;
}

interface IiOSSimulatorService extends IEmulatorPlatformServices {
postDarwinNotification(notification: string): Promise<void>;

/**
* Tries to connect to specified port for speciefied amount of time.
* In case it succeeds, a socket is returned.
* In case it fails, undefined is returned.
* @param {IConnectToPortData} connectToPortData Data describing port and timeout to try to connect.
* @returns {net.Socket} Returns instance of net.Socket when connection is successful, otherwise undefined is returned.
*/
connectToPort(connectToPortData: IConnectToPortData): Promise<any>;
}

interface IEmulatorSettingsService {
Expand Down
44 changes: 44 additions & 0 deletions helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,53 @@ import { ReadStream } from "tty";
import { Configurations } from "./constants";
import { EventEmitter } from "events";
import * as crypto from "crypto";
import progress = require("progress-stream");
import filesize = require("filesize");
import * as util from "util";

const Table = require("cli-table");

export function trackDownloadProgress(destinationStream: NodeJS.WritableStream, url: string): NodeJS.ReadableStream {
// \r for carriage return doesn't work on windows in node for some reason so we have to use it's hex representation \x1B[0G
let lastMessageSize = 0;
const carriageReturn = "\x1B[0G";
let timeElapsed = 0;

const isInteractiveTerminal = isInteractive();
const progressStream = progress({ time: 1000 }, (progress: any) => {
timeElapsed = progress.runtime;

if (timeElapsed >= 1) {
if (isInteractiveTerminal) {
this.$logger.write("%s%s", carriageReturn, Array(lastMessageSize + 1).join(" "));

const message = util.format("%sDownload progress ... %s | %s | %s/s",
carriageReturn,
Math.floor(progress.percentage) + "%",
filesize(progress.transferred),
filesize(progress.speed));

this.$logger.write(message);
lastMessageSize = message.length;
}
}
});

progressStream.on("finish", () => {
if (timeElapsed >= 1) {
const msg = `Download of ${url} completed.`;
if (isInteractiveTerminal) {
this.$logger.out("%s%s%s%s", carriageReturn, Array(lastMessageSize + 1).join(" "), carriageReturn, msg);
} else {
this.$logger.out(msg);
}
}
});

progressStream.pipe(destinationStream);
return progressStream;
}

export async function executeActionByChunks<T>(initialData: T[] | IDictionary<T>, chunkSize: number, elementAction: (element: T, key?: string | number) => Promise<any>): Promise<void> {
let arrayToChunk: (T | string)[];
let action: (key: string | T) => Promise<any>;
Expand Down
40 changes: 2 additions & 38 deletions http-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import { EOL } from "os";
import * as helpers from "./helpers";
import * as zlib from "zlib";
import * as util from "util";
import progress = require("progress-stream");
import filesize = require("filesize");
import { HttpStatusCodes } from "./constants";
import * as request from "request";

Expand Down Expand Up @@ -133,8 +131,6 @@ export class HttpClient implements Server.IHttpClient {
this.setResponseResult(promiseActions, timerId, { response });
});

pipeTo = this.trackDownloadProgress(pipeTo);

responseStream.pipe(pipeTo);
} else {
const data: string[] = [];
Expand Down Expand Up @@ -204,39 +200,6 @@ export class HttpClient implements Server.IHttpClient {
}
}

private trackDownloadProgress(pipeTo: NodeJS.WritableStream): NodeJS.ReadableStream {
// \r for carriage return doesn't work on windows in node for some reason so we have to use it's hex representation \x1B[0G
let lastMessageSize = 0;
const carriageReturn = "\x1B[0G";
let timeElapsed = 0;

const progressStream = progress({ time: 1000 }, (progress: any) => {
timeElapsed = progress.runtime;

if (timeElapsed >= 1) {
this.$logger.write("%s%s", carriageReturn, Array(lastMessageSize + 1).join(" "));

const message = util.format("%sDownload progress ... %s | %s | %s/s",
carriageReturn,
Math.floor(progress.percentage) + "%",
filesize(progress.transferred),
filesize(progress.speed));

this.$logger.write(message);
lastMessageSize = message.length;
}
});

progressStream.on("finish", () => {
if (timeElapsed >= 1) {
this.$logger.out("%s%s%s%s", carriageReturn, Array(lastMessageSize + 1).join(" "), carriageReturn, "Download completed.");
}
});

progressStream.pipe(pipeTo);
return progressStream;
}

private getErrorMessage(statusCode: number, body: string): string {
if (statusCode === HttpStatusCodes.PROXY_AUTHENTICATION_REQUIRED) {
const clientNameLowerCase = this.$staticConfig.CLIENT_NAME.toLowerCase();
Expand All @@ -262,7 +225,8 @@ export class HttpClient implements Server.IHttpClient {
return err.Message;
}
} catch (parsingFailed) {
return `The server returned unexpected response: ${parsingFailed.toString()}`;
this.$logger.trace("Failed to get error from http request: ", parsingFailed);
return `The server returned unexpected response: ${body}`;
}

return body;
Expand Down
14 changes: 14 additions & 0 deletions mobile/ios/simulator/ios-emulator-services.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import * as net from "net";
import { connectEventuallyUntilTimeout } from "../../../helpers";

class IosEmulatorServices implements Mobile.IiOSSimulatorService {
private static DEFAULT_TIMEOUT = 10000;

constructor(private $logger: ILogger,
private $emulatorSettingsService: Mobile.IEmulatorSettingsService,
private $errors: IErrors,
Expand Down Expand Up @@ -58,6 +63,15 @@ class IosEmulatorServices implements Mobile.IiOSSimulatorService {
await this.$childProcess.spawnFromEvent(nodeCommandName, iosSimArgs, "close", { stdio: "inherit" });
}

public async connectToPort(data: Mobile.IConnectToPortData): Promise<net.Socket> {
try {
const socket = await connectEventuallyUntilTimeout(() => net.connect(data.port), data.timeout || IosEmulatorServices.DEFAULT_TIMEOUT);
return socket;
} catch (e) {
this.$logger.debug(e);
}
}

private async runApplicationOnEmulatorCore(app: string, emulatorOptions?: Mobile.IEmulatorOptions): Promise<any> {
this.$logger.info("Starting iOS Simulator");
const iosSimPath = this.$iOSSimResolver.iOSSimPath;
Expand Down
4 changes: 4 additions & 0 deletions os-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ export class OsInfo implements IOsInfo {
public arch(): string {
return os.arch();
}

public platform(): string {
return os.platform();
}
}

$injector.register("osInfo", OsInfo);
29 changes: 24 additions & 5 deletions progress-indicator.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
import { isInteractive } from './helpers';

const clui = require("clui");

export class ProgressIndicator implements IProgressIndicator {
constructor(private $logger: ILogger) { }

public async showProgressIndicator<T>(promise: Promise<T>, timeout: number, options?: { surpressTrailingNewLine?: boolean }): Promise<T> {
const surpressTrailingNewLine = options && options.surpressTrailingNewLine;

let isResolved = false;
let isFulfilled = false;

const tempPromise = new Promise<T>((resolve, reject) => {
promise.then((res) => {
isResolved = true;
isFulfilled = true;
resolve(res);
}, (err) => {
isResolved = true;
isFulfilled = true;
reject(err);
});
});

while (!isResolved) {
await this.$logger.printMsgWithTimeout(".", timeout);
if (!isInteractive()) {
while (!isFulfilled) {
await this.$logger.printMsgWithTimeout(".", timeout);
}
}

if (!surpressTrailingNewLine) {
Expand All @@ -26,5 +32,18 @@ export class ProgressIndicator implements IProgressIndicator {

return tempPromise;
}

public getSpinner(message: string): ISpinner {
if (isInteractive()) {
return new clui.Spinner(message);
} else {
let msg = message;
return {
start: () => this.$logger.info(msg),
message: (newMsg: string) => msg = newMsg,
stop: (): void => undefined
};
}
}
}
$injector.register("progressIndicator", ProgressIndicator);
Loading