Skip to content

Feat: Quality of life improvements #5757

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
9 changes: 9 additions & 0 deletions lib/bootstrap.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { injector } from "./common/yok";

require("./common/bootstrap");

injector.requirePublicClass("logger", "./common/logger/logger");
injector.require("config", "./config");
injector.require("options", "./options");
Expand Down Expand Up @@ -278,6 +279,7 @@ injector.require(
"./helpers/android-bundle-validator-helper"
);
injector.require("liveSyncCommandHelper", "./helpers/livesync-command-helper");

injector.require("deployCommandHelper", "./helpers/deploy-command-helper");
injector.require("platformCommandHelper", "./helpers/platform-command-helper");
injector.require("optionsTracker", "./helpers/options-track-helper");
Expand Down Expand Up @@ -442,3 +444,10 @@ injector.require(
injector.require("tempService", "./services/temp-service");

injector.require("sharedEventBus", "./shared-event-bus");

injector.require("keyCommandHelper", "./helpers/key-command-helper");

injector.requireCommand("start", "./commands/start");
injector.require("startService", "./services/start-service");

require("./key-commands/bootstrap");
5 changes: 5 additions & 0 deletions lib/color.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
// using chalk as some of our other dependencies are already using it...
// exporting from here so we can easily refactor to a different color library if needed
import * as ansi from "ansi-colors";
import * as chalk from "chalk";

export type Color = typeof chalk.Color;

export function stripColors(formatStr: string) {
return ansi.stripColor(formatStr);
}

export const color = chalk;
37 changes: 23 additions & 14 deletions lib/commands/run.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import { ERROR_NO_VALID_SUBCOMMAND_FORMAT } from "../common/constants";
import {
ANDROID_RELEASE_BUILD_ERROR_MESSAGE,
ANDROID_APP_BUNDLE_SIGNING_ERROR_MESSAGE,
} from "../constants";
import { IErrors, IHostInfo } from "../common/declarations";
import { cache } from "../common/decorators";
import { hasValidAndroidSigning } from "../common/helpers";
import { IProjectData, IProjectDataService } from "../definitions/project";
import { IMigrateController } from "../definitions/migrate";
import { IOptions, IPlatformValidationService } from "../declarations";
import { ICommand, ICommandParameter } from "../common/definitions/commands";
import { IErrors, IHostInfo } from "../common/declarations";
import {
IKeyCommandHelper,
IKeyCommandPlatform,
} from "../common/definitions/key-commands";
import { IInjector } from "../common/definitions/yok";
import { hasValidAndroidSigning } from "../common/helpers";
import { injector } from "../common/yok";
import {
ANDROID_APP_BUNDLE_SIGNING_ERROR_MESSAGE,
ANDROID_RELEASE_BUILD_ERROR_MESSAGE,
} from "../constants";
import { IOptions, IPlatformValidationService } from "../declarations";
import { IMigrateController } from "../definitions/migrate";
import { IProjectData, IProjectDataService } from "../definitions/project";

export class RunCommandBase implements ICommand {
private liveSyncCommandHelperAdditionalOptions: ILiveSyncCommandHelperAdditionalOptions = <
ILiveSyncCommandHelperAdditionalOptions
>{};
private liveSyncCommandHelperAdditionalOptions: ILiveSyncCommandHelperAdditionalOptions =
<ILiveSyncCommandHelperAdditionalOptions>{};

public platform: string;
constructor(
Expand All @@ -26,15 +29,21 @@ export class RunCommandBase implements ICommand {
private $liveSyncCommandHelper: ILiveSyncCommandHelper,
private $migrateController: IMigrateController,
private $options: IOptions,
private $projectData: IProjectData
private $projectData: IProjectData,
private $keyCommandHelper: IKeyCommandHelper
) {}

public allowedParameters: ICommandParameter[] = [];
public async execute(args: string[]): Promise<void> {
return this.$liveSyncCommandHelper.executeCommandLiveSync(
await this.$liveSyncCommandHelper.executeCommandLiveSync(
this.platform,
this.liveSyncCommandHelperAdditionalOptions
);

this.$keyCommandHelper.attachKeyCommands(
this.platform as IKeyCommandPlatform,
"run"
);
}

public async canExecute(args: string[]): Promise<boolean> {
Expand Down
17 changes: 17 additions & 0 deletions lib/commands/start.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ICommand, ICommandParameter } from "../common/definitions/commands";
import { injector } from "../common/yok";
import { IStartService } from "../definitions/start-service";

export class StartCommand implements ICommand {
constructor(private $startService: IStartService) {}
async execute(args: string[]): Promise<void> {
this.$startService.start();
return;
}
allowedParameters: ICommandParameter[];
async canExecute?(args: string[]): Promise<boolean> {
return true;
}
}

injector.registerCommand("start", StartCommand);
52 changes: 52 additions & 0 deletions lib/common/definitions/key-commands.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
export type IKeyCommandPlatform = "Android" | "iOS" | "all";
export type IKeysLowerCase =
| "a"
| "b"
| "c"
| "d"
| "e"
| "f"
| "g"
| "h"
| "i"
| "j"
| "k"
| "l"
| "m"
| "n"
| "o"
| "p"
| "q"
| "r"
| "s"
| "t"
| "u"
| "v"
| "w"
| "x"
| "y"
| "z";

export type IValidKeyCommands = IKeysLowerCase | `${Uppercase<IKeysLowerCase>}`;

export interface IKeyCommandHelper {
attachKeyCommands: (
platform: IKeyCommandPlatform,
processType: SupportedProcessType
) => void;

addOverride(key: IValidKeyCommands, execute: () => Promise<boolean>);
removeOverride(key: IValidKeyCommands);
printCommands(platform: IKeyCommandPlatform): void;
}

export type SupportedProcessType = "start" | "run";

export interface IKeyCommand {
key: IValidKeyCommands;
platform: IKeyCommandPlatform;
description: string;
willBlockKeyCommandExecution?: boolean;
execute(platform: string): Promise<void>;
canExecute?: (processType: SupportedProcessType) => boolean;
}
5 changes: 5 additions & 0 deletions lib/common/definitions/yok.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { IDisposable, IDictionary } from "../declarations";
import { ICommand } from "./commands";
import { IKeyCommand, IValidKeyCommands } from "./key-commands";

interface IInjector extends IDisposable {
require(name: string, file: string): void;
Expand All @@ -8,6 +9,7 @@ interface IInjector extends IDisposable {
requirePublicClass(names: string | string[], file: string): void;
requireCommand(name: string, file: string): void;
requireCommand(names: string[], file: string): void;
requireKeyCommand(name: string, file: string): void;
/**
* Resolves an implementation by constructor function.
* The injector will create new instances for every call.
Expand All @@ -22,10 +24,13 @@ interface IInjector extends IDisposable {
resolve<T>(name: string, ctorArguments?: IDictionary<any>): T;

resolveCommand(name: string): ICommand;
resolveKeyCommand(key: string): IKeyCommand;
register(name: string, resolver: any, shared?: boolean): void;
registerCommand(name: string, resolver: any): void;
registerCommand(names: string[], resolver: any): void;
registerKeyCommand(key: IValidKeyCommands, resolver: any): void;
getRegisteredCommandsNames(includeDev: boolean): string[];
getRegisteredKeyCommandsNames(): string[];
dynamicCallRegex: RegExp;
dynamicCall(call: string, args?: any[]): Promise<any>;
isDefaultCommand(commandName: string): boolean;
Expand Down
28 changes: 28 additions & 0 deletions lib/common/header.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { color, stripColors } from "../color";

export function printHeader() {
if (process.env.HIDE_HEADER) return;
const version = "8.5.3";
const middle = [
color.dim("│ "),
color.cyanBright.bold(" {N} NativeScript "),
color.whiteBright.bold("CLI"),
color.dim(` [v${version}] `),
color.dim(" │"),
].join("");
const middle2 = [
color.dim("│ "),
color.whiteBright.bold(" Empowering JS with Native APIs "),
color.dim(" │"),
].join("");

const end = [color.dim("─┘")].join("");

const width = stripColors(middle).length;
const endWidth = stripColors(end).length;
console.info(" ");
console.info(" " + color.dim("┌" + "─".repeat(width - 2) + "┐"));
console.info(" " + middle);
console.info(" " + middle2);
console.info(" " + color.dim("└" + "─".repeat(width - endWidth - 1)) + end);
}
4 changes: 2 additions & 2 deletions lib/common/mobile/mobile-core/android-device-discovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ interface IAdbAndroidDeviceInfo {

export class AndroidDeviceDiscovery
extends DeviceDiscovery
implements Mobile.IAndroidDeviceDiscovery {
implements Mobile.IAndroidDeviceDiscovery
{
private _devices: IAdbAndroidDeviceInfo[] = [];
private isStarted: boolean;

Expand Down Expand Up @@ -56,7 +57,6 @@ export class AndroidDeviceDiscovery

private async checkForDevices(): Promise<void> {
const devices = await this.$adb.getDevices();

await this.checkCurrentData(devices);
}

Expand Down
38 changes: 19 additions & 19 deletions lib/common/mobile/mobile-core/devices-service.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
import * as util from "util";
import * as helpers from "../../helpers";
import * as assert from "assert";
import * as _ from "lodash";
import * as constants from "../../constants";
import { exported } from "../../decorators";
import { settlePromises } from "../../helpers";
import { EventEmitter } from "events";
import * as _ from "lodash";
import { EOL } from "os";
import { CONNECTED_STATUS } from "../../constants";
import { isInteractive } from "../../helpers";
import * as util from "util";
import { DebugCommandErrors } from "../../../constants";
import { performanceLog } from "../../decorators";
import { IOptions } from "../../../declarations";
import * as constants from "../../constants";
import { CONNECTED_STATUS } from "../../constants";
import {
IAppInstalledInfo,
IDictionary,
IErrors,
IHostInfo,
IAppInstalledInfo,
} from "../../declarations";
import { exported, performanceLog } from "../../decorators";
import { IInjector } from "../../definitions/yok";
import * as helpers from "../../helpers";
import { isInteractive, settlePromises } from "../../helpers";
import { injector } from "../../yok";
import { IOptions } from "../../../declarations";

export class DevicesService
extends EventEmitter
implements Mobile.IDevicesService {
implements Mobile.IDevicesService
{
private static DEVICE_LOOKING_INTERVAL = 200;
private static EMULATOR_IMAGES_DETECTION_INTERVAL = 60 * 1000;
private _devices: IDictionary<Mobile.IDevice> = {};
Expand Down Expand Up @@ -190,9 +189,10 @@ export class DevicesService
const availableEmulatorsOutput = await this.getEmulatorImages({
platform: options.platform,
});
const emulators = this.$emulatorHelper.getEmulatorsFromAvailableEmulatorsOutput(
availableEmulatorsOutput
);
const emulators =
this.$emulatorHelper.getEmulatorsFromAvailableEmulatorsOutput(
availableEmulatorsOutput
);
const errors = this.$emulatorHelper.getErrorsFromAvailableEmulatorsOutput(
availableEmulatorsOutput
);
Expand Down Expand Up @@ -893,7 +893,7 @@ export class DevicesService
// TODO: Remove from here as it calls startLookingForDevices, so we double the calls to specific device detection services
await this.startEmulatorIfNecessary(deviceInitOpts);
}

deviceInitOpts;
const platform = deviceInitOpts.platform;
const deviceOption = deviceInitOpts.deviceId;
const deviceLookingOptions: Mobile.IDeviceLookingOptions = {
Expand All @@ -910,6 +910,7 @@ export class DevicesService
);
await this.startLookingForDevices(deviceLookingOptions);
this._device = await this.getDevice(deviceOption);

if (this._device.deviceInfo.platform !== this._platform) {
this.$errors.fail(constants.ERROR_CANNOT_RESOLVE_DEVICE);
}
Expand Down Expand Up @@ -1023,9 +1024,8 @@ export class DevicesService
appIdentifier: string
): Promise<Mobile.IDebugWebViewInfo[]> {
const device = this.getDeviceByIdentifier(deviceIdentifier),
debuggableViewsPerApp = await device.applicationManager.getDebuggableAppViews(
[appIdentifier]
);
debuggableViewsPerApp =
await device.applicationManager.getDebuggableAppViews([appIdentifier]);

return debuggableViewsPerApp && debuggableViewsPerApp[appIdentifier];
}
Expand Down
14 changes: 8 additions & 6 deletions lib/common/services/commands-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
ICommand,
ISimilarCommand,
} from "../definitions/commands";
import { printHeader } from "../header";

class CommandArgumentsValidationHelper {
constructor(public isValid: boolean, _remainingArguments: string[]) {
Expand Down Expand Up @@ -65,9 +66,8 @@ export class CommandsService implements ICommandsService {
!command.disableAnalytics &&
!this.$options.disableAnalytics
) {
const analyticsService = this.$injector.resolve<IAnalyticsService>(
"analyticsService"
); // This should be resolved here due to cyclic dependency
const analyticsService =
this.$injector.resolve<IAnalyticsService>("analyticsService"); // This should be resolved here due to cyclic dependency
await analyticsService.checkConsent();

const beautifiedCommandName = this.beautifyCommandName(
Expand Down Expand Up @@ -183,6 +183,7 @@ export class CommandsService implements ICommandsService {
: canExecuteResult;

if (canExecute) {
printHeader();
await this.executeCommandAction(
commandName,
commandArguments,
Expand Down Expand Up @@ -246,9 +247,10 @@ export class CommandsService implements ICommandsService {
defaultCommandDelimiter: CommandsDelimiters.DefaultHierarchicalCommand,
};

const extensionData = await this.$extensibilityService.getExtensionNameWhereCommandIsRegistered(
commandInfo
);
const extensionData =
await this.$extensibilityService.getExtensionNameWhereCommandIsRegistered(
commandInfo
);

if (extensionData) {
this.$logger.warn(extensionData.installationMessage);
Expand Down
Loading