Skip to content
This repository was archived by the owner on Feb 2, 2021. It is now read-only.
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
4 changes: 2 additions & 2 deletions appbuilder/device-emitter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { EventEmitter } from "events";
import { DeviceDiscoveryEventNames } from "../constants";
import { DeviceDiscoveryEventNames, DEVICE_LOG_EVENT_NAME } from "../constants";

export class DeviceEmitter extends EventEmitter {
constructor(private $deviceLogProvider: EventEmitter,
Expand Down Expand Up @@ -34,7 +34,7 @@ export class DeviceEmitter extends EventEmitter {
});

this.$deviceLogProvider.on("data", (identifier: string, data: any) => {
this.emit('deviceLogData', identifier, data.toString());
this.emit(DEVICE_LOG_EVENT_NAME, identifier, data.toString());
});
}

Expand Down
2 changes: 2 additions & 0 deletions appbuilder/proton-static-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,7 @@ export class ProtonStaticConfig extends StaticConfigBase {
public CLIENT_NAME = "Desktop Client - Universal";

public ANALYTICS_EXCEPTIONS_API_KEY: string = null;

public PROFILE_DIR_NAME: string = ".appbuilder-desktop-universal";
}
$injector.register("staticConfig", ProtonStaticConfig);
2 changes: 1 addition & 1 deletion bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ $injector.require("dynamicHelpService", "./services/dynamic-help-service");
$injector.require("microTemplateService", "./services/micro-templating-service");
$injector.require("mobileHelper", "./mobile/mobile-helper");
$injector.require("devicePlatformsConstants", "./mobile/device-platforms-constants");
$injector.require("htmlHelpService", "./services/html-help-service");
$injector.require("helpService", "./services/help-service");
$injector.require("messageContractGenerator", "./services/message-contract-generator");
$injector.require("proxyService", "./services/proxy-service");
$injector.require("credentialsService", "./services/credentials-service");
Expand Down
17 changes: 4 additions & 13 deletions commands/help.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { EOL } from "os";

export class HelpCommand implements ICommand {
constructor(private $logger: ILogger,
private $injector: IInjector,
private $htmlHelpService: IHtmlHelpService,
private $staticConfig: Config.IStaticConfig,
constructor(private $injector: IInjector,
private $helpService: IHelpService,
private $options: ICommonOptions) { }

public enableHooks = false;
Expand All @@ -22,14 +18,9 @@ export class HelpCommand implements ICommand {
}

if (this.$options.help) {
const help = await this.$htmlHelpService.getCommandLineHelpForCommand(topic);
if (this.$staticConfig.FULL_CLIENT_NAME) {
this.$logger.info(this.$staticConfig.FULL_CLIENT_NAME.green.bold + EOL);
}

this.$logger.printMarkdown(help);
await this.$helpService.showCommandLineHelp(topic);
} else {
await this.$htmlHelpService.openHelpForCommandInBrowser(topic);
await this.$helpService.openHelpForCommandInBrowser(topic);
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions commands/post-install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ export class PostInstallCommand implements ICommand {
constructor(private $fs: IFileSystem,
private $staticConfig: Config.IStaticConfig,
private $commandsService: ICommandsService,
private $htmlHelpService: IHtmlHelpService,
private $options: ICommonOptions,
private $helpService: IHelpService,
private $settingsService: ISettingsService,
private $doctorService: IDoctorService,
private $analyticsService: IAnalyticsService,
private $logger: ILogger) {
Expand All @@ -18,11 +18,11 @@ export class PostInstallCommand implements ICommand {
// it is no longer accessible for the user initiating the installation
// patch the owner here
if (process.env.SUDO_USER) {
await this.$fs.setCurrentUserAsOwner(this.$options.profileDir, process.env.SUDO_USER);
await this.$fs.setCurrentUserAsOwner(this.$settingsService.getProfileDir(), process.env.SUDO_USER);
}
}

await this.$htmlHelpService.generateHtmlPages();
await this.$helpService.generateHtmlPages();

const doctorResult = await this.$doctorService.printWarnings({ trackResult: false });
// Explicitly ask for confirmation of usage-reporting:
Expand Down
4 changes: 2 additions & 2 deletions commands/preuninstall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ export class PreUninstallCommand implements ICommand {
public allowedParameters: ICommandParameter[] = [];

constructor(private $fs: IFileSystem,
private $options: ICommonOptions) { }
private $settingsService: ISettingsService) { }

public async execute(args: string[]): Promise<void> {
this.$fs.deleteFile(path.join(this.$options.profileDir, "KillSwitches", "cli"));
this.$fs.deleteFile(path.join(this.$settingsService.getProfileDir(), "KillSwitches", "cli"));
}
}

Expand Down
2 changes: 2 additions & 0 deletions constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export class DeviceDiscoveryEventNames {
static DEVICE_LOST = "deviceLost";
}

export const DEVICE_LOG_EVENT_NAME = "deviceLogData";

export const TARGET_FRAMEWORK_IDENTIFIERS = {
Cordova: "Cordova",
NativeScript: "NativeScript"
Expand Down
37 changes: 28 additions & 9 deletions declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,13 @@ interface IConfigurationSettings {
* This string will be used when constructing the UserAgent http header.
* @type {string}
*/
userAgentName: string;
userAgentName?: string;

/**
* Describes the profile directory that will be used for various CLI settings, like user-settings.json file location, extensions, etc.
* @type {string}
*/
profileDir?: string;
}

/**
Expand All @@ -92,6 +98,12 @@ interface ISettingsService {
* @returns {void}
*/
setSettings(settings: IConfigurationSettings): void;

/**
* Returns currently used profile directory.
* @returns {string}
*/
getProfileDir(): string;
}

/**
Expand Down Expand Up @@ -540,7 +552,7 @@ interface IErrors {
fail(formatStr: string, ...args: any[]): never;
fail(opts: { formatStr?: string; errorCode?: number; suppressCommandHelp?: boolean }, ...args: any[]): never;
failWithoutHelp(message: string, ...args: any[]): never;
beginCommand(action: () => Promise<boolean>, printCommandHelp: () => Promise<boolean>): Promise<boolean>;
beginCommand(action: () => Promise<boolean>, printCommandHelp: () => Promise<void>): Promise<boolean>;
verifyHeap(message: string): void;
printCallStack: boolean;
}
Expand Down Expand Up @@ -721,6 +733,13 @@ interface IAnalyticsSettingsService {
* @returns {Promise<string>}
*/
getClientId(): Promise<string>;

/**
* Gets user agent string identifing the current system in the following format: `${identifier} (${systemInfo}) ${osArch}`
* @param {string} identifier The product identifier.
* @returns {string} The user agent string.
*/
getUserAgentString(identifier: string): string;
}

interface IHostCapabilities {
Expand Down Expand Up @@ -948,17 +967,17 @@ interface IMicroTemplateService {
parseContent(data: string, options: { isHtml: boolean }): Promise<string>;
}

interface IHtmlHelpService {
interface IHelpService {
generateHtmlPages(): Promise<void>;

openHelpForCommandInBrowser(commandName: string): Promise<void>;

/**
* Gets the help content for a specific command that should be shown on the terminal.
* @param {string} commandName Name of the command for which to read the help.
* @returns {Promise<string>} Help content of the command parsed with all terminal rules applied (stripped content that should be shown only for html help).
* Shows command line help for specified command.
* @param {string} commandName The name of the command for which to show the help.
* @returns {Promise<void>}
*/
getCommandLineHelpForCommand(commandName: string): Promise<string>;

openHelpForCommandInBrowser(commandName: string): Promise<void>;
showCommandLineHelp(commandName: string): Promise<void>;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion definitions/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ declare module Config {
ERROR_REPORT_SETTING_NAME: string;
SYS_REQUIREMENTS_LINK: string;
version: string;
helpTextPath: string;
getAdbFilePath(): Promise<string>;
disableAnalytics?: boolean;
disableCommandHooks?: boolean;
Expand All @@ -29,6 +28,7 @@ declare module Config {
PATH_TO_BOOTSTRAP: string;
QR_SIZE: number;
INSTALLATION_SUCCESS_MESSAGE?: string;
PROFILE_DIR_NAME: string
}

interface IConfig {
Expand Down
10 changes: 8 additions & 2 deletions definitions/mobile.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ declare module Mobile {
isEmulator: boolean;
openDeviceLogStream(): Promise<void>;
getApplicationInfo(applicationIdentifier: string): Promise<Mobile.IApplicationInfo>;

/**
* Called when device is lost. Its purpose is to clean any resources used by the instance.
* @returns {void}
*/
detach?(): void;
}

interface IiOSDevice extends IDevice {
Expand Down Expand Up @@ -767,14 +773,14 @@ declare module Mobile {
}
}

interface IIOSDeviceOperations extends IDisposable {
interface IIOSDeviceOperations extends IDisposable, NodeJS.EventEmitter {
install(ipaPath: string, deviceIdentifiers: string[], errorHandler?: DeviceOperationErrorHandler): Promise<IOSDeviceResponse>;

uninstall(appIdentifier: string, deviceIdentifiers: string[], errorHandler?: DeviceOperationErrorHandler): Promise<IOSDeviceResponse>;

startLookingForDevices(deviceFoundCallback: DeviceInfoCallback, deviceLostCallback: DeviceInfoCallback, options?: Mobile.IDeviceLookingOptions): Promise<void>;

startDeviceLog(deviceIdentifier: string, printLogFunction: (response: IOSDeviceLib.IDeviceLogData) => void): void;
startDeviceLog(deviceIdentifier: string): void;

apps(deviceIdentifiers: string[], errorHandler?: DeviceOperationErrorHandler): Promise<IOSDeviceAppInfo>;

Expand Down
2 changes: 1 addition & 1 deletion errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ export class Errors implements IErrors {
return this.fail({ formatStr: util.format.apply(null, args), suppressCommandHelp: true });
}

public async beginCommand(action: () => Promise<boolean>, printCommandHelp: () => Promise<boolean>): Promise<boolean> {
public async beginCommand(action: () => Promise<boolean>, printCommandHelp: () => Promise<void>): Promise<boolean> {
try {
return await action();
} catch (ex) {
Expand Down
19 changes: 14 additions & 5 deletions mobile/ios/device/ios-device-operations.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { IOSDeviceLib as IOSDeviceLibModule } from "ios-device-lib";
import { cache } from "../../../decorators";
import { DEVICE_LOG_EVENT_NAME } from "../../../constants";
import assert = require("assert");
import { EventEmitter } from "events";

export class IOSDeviceOperations implements IIOSDeviceOperations, IDisposable {
export class IOSDeviceOperations extends EventEmitter implements IIOSDeviceOperations, IDisposable {
public isInitialized: boolean;
public shouldDispose: boolean;
private deviceLib: IOSDeviceLib.IOSDeviceLib;

constructor(private $logger: ILogger,
private $processService: IProcessService) {
super();

this.isInitialized = false;
this.shouldDispose = true;
this.$processService.attachToProcessExitSignals(this, () => {
Expand Down Expand Up @@ -67,15 +71,13 @@ export class IOSDeviceOperations implements IIOSDeviceOperations, IDisposable {
}
}

public startDeviceLog(deviceIdentifier: string, printLogFunction: (response: IOSDeviceLib.IDeviceLogData) => void): void {
public startDeviceLog(deviceIdentifier: string): void {
this.assertIsInitialized();
this.setShouldDispose(false);

this.$logger.trace(`Printing device log for device with identifier: ${deviceIdentifier}.`);

this.deviceLib.on("deviceLogData", (response: IOSDeviceLib.IDeviceLogData) => {
printLogFunction(response);
});
this.attacheDeviceLogDataHandler();

this.deviceLib.startDeviceLog([deviceIdentifier]);
}
Expand Down Expand Up @@ -230,6 +232,13 @@ export class IOSDeviceOperations implements IIOSDeviceOperations, IDisposable {
private assertIsInitialized(): void {
assert.ok(this.isInitialized, "iOS device operations not initialized.");
}

@cache()
private attacheDeviceLogDataHandler(): void {
this.deviceLib.on(DEVICE_LOG_EVENT_NAME, (response: IOSDeviceLib.IDeviceLogData) => {
this.emit(DEVICE_LOG_EVENT_NAME, response);
});
}
}

$injector.register("iosDeviceOperations", IOSDeviceOperations);
23 changes: 18 additions & 5 deletions mobile/ios/device/ios-device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import * as applicationManagerPath from "./ios-application-manager";
import * as fileSystemPath from "./ios-device-file-system";
import * as constants from "../../../constants";
import * as net from "net";
import { cache } from "../../../decorators";

export class IOSDevice implements Mobile.IiOSDevice {
public applicationManager: Mobile.IDeviceApplicationManager;
public fileSystem: Mobile.IDeviceFileSystem;
public deviceInfo: Mobile.IDeviceInfo;

private _socket: net.Socket;
private _deviceLogHandler: Function;

constructor(private deviceActionInfo: IOSDeviceLib.IDeviceActionInfo,
private $injector: IInjector,
Expand Down Expand Up @@ -48,13 +50,24 @@ export class IOSDevice implements Mobile.IiOSDevice {
return this.applicationManager.getApplicationInfo(applicationIdentifier);
}

private actionOnDeviceLog(response: IOSDeviceLib.IDeviceLogData): void {
if (response.deviceId === this.deviceInfo.identifier) {
this.$deviceLogProvider.logData(response.message, this.$devicePlatformsConstants.iOS, this.deviceInfo.identifier);
}
}

@cache()
public async openDeviceLogStream(): Promise<void> {
if (this.deviceInfo.status !== constants.UNREACHABLE_STATUS) {
this.$iosDeviceOperations.startDeviceLog(this.deviceInfo.identifier, (response: IOSDeviceLib.IDeviceLogData) => {
if (response.deviceId === this.deviceInfo.identifier) {
this.$deviceLogProvider.logData(response.message, this.$devicePlatformsConstants.iOS, this.deviceInfo.identifier);
}
});
this.$iosDeviceOperations.startDeviceLog(this.deviceInfo.identifier);
this._deviceLogHandler = this.actionOnDeviceLog.bind(this);
this.$iosDeviceOperations.on(constants.DEVICE_LOG_EVENT_NAME, this._deviceLogHandler);
}
}

public detach(): void {
if (this._deviceLogHandler) {
this.$iosDeviceOperations.removeListener(constants.DEVICE_LOG_EVENT_NAME, this._deviceLogHandler);
}
}

Expand Down
5 changes: 5 additions & 0 deletions mobile/mobile-core/devices-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ export class DevicesService extends EventEmitter implements Mobile.IDevicesServi

private onDeviceLost(device: Mobile.IDevice): void {
this.$logger.trace(`Lost device with identifier '${device.deviceInfo.identifier}'`);

if (device.detach) {
device.detach();
}

delete this._devices[device.deviceInfo.identifier];
this.emit(constants.DeviceDiscoveryEventNames.DEVICE_LOST, device);
}
Expand Down
17 changes: 12 additions & 5 deletions options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ export class OptionsBase {
verbose: { type: OptionType.Boolean, alias: "v" },
version: { type: OptionType.Boolean },
help: { type: OptionType.Boolean, alias: "h" },
profileDir: { type: OptionType.String, default: this.defaultProfileDir },
profileDir: { type: OptionType.String },
analyticsClient: { type: OptionType.String },
path: { type: OptionType.String, alias: "p" },
// This will parse all non-hyphenated values as strings.
_: { type: OptionType.String }
};

constructor(public options: IDictionary<IDashedOption>,
public defaultProfileDir: string,
private $errors: IErrors,
private $staticConfig: Config.IStaticConfig) {
private $staticConfig: Config.IStaticConfig,
private $settingsService: ISettingsService) {

this.options = _.extend({}, this.commonOptions, this.options, this.globalOptions);
this.setArgv();
Expand Down Expand Up @@ -180,17 +180,24 @@ export class OptionsBase {
});

this.argv = yargs(process.argv.slice(2)).options(opts).argv;

// For backwards compatibility
// Previously profileDir had a default option and calling `this.$options.profileDir` always returned valid result.
// Now the profileDir should be used from $settingsService, but ensure the `this.$options.profileDir` returns the same value.
this.$settingsService.setSettings({ profileDir: this.argv.profileDir});
this.argv.profileDir = this.argv["profile-dir"] = this.$settingsService.getProfileDir();

this.adjustDashedOptions();
}

private adjustDashedOptions(): void {
_.each(this.optionNames, optionName => {
Object.defineProperty(OptionsBase.prototype, optionName, {
configurable: true,
get: function () {
get: () => {
return this.getOptionValue(optionName);
},
set: function (value: any) {
set: (value: any) => {
this.argv[optionName] = value;
}
});
Expand Down
Loading