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 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
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;
18 changes: 10 additions & 8 deletions lib/commands/clean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from "../definitions/project";

import type { PromptObject } from "prompts";
import { IOptions } from "../declarations";
import { IOptions, IStaticConfig } from "../declarations";
import {
ITerminalSpinner,
ITerminalSpinnerService,
Expand All @@ -22,8 +22,6 @@ import { resolve } from "path";
import { readdir } from "fs/promises";
import { isInteractive } from "../common/helpers";

const CLIPath = resolve(__dirname, "..", "..", "bin", "nativescript.js");

function bytesToHumanReadable(bytes: number): string {
const units = ["B", "KB", "MB", "GB", "TB"];
let unit = 0;
Expand Down Expand Up @@ -90,7 +88,8 @@ export class CleanCommand implements ICommand {
private $prompter: IPrompter,
private $logger: ILogger,
private $options: IOptions,
private $childProcess: IChildProcess
private $childProcess: IChildProcess,
private $staticConfig: IStaticConfig
) {}

public async execute(args: string[]): Promise<void> {
Expand Down Expand Up @@ -198,9 +197,12 @@ export class CleanCommand implements ICommand {
paths,
(p) => {
return this.$childProcess
.exec(`node ${CLIPath} clean --dry-run --json --disable-analytics`, {
cwd: p,
})
.exec(
`node ${this.$staticConfig.cliBinPath} clean --dry-run --json --disable-analytics`,
{
cwd: p,
}
)
.then((res) => {
const paths: Record<string, number> = JSON.parse(res).stats;
return Object.values(paths).reduce((a, b) => a + b, 0);
Expand Down Expand Up @@ -290,7 +292,7 @@ export class CleanCommand implements ICommand {

const ok = await this.$childProcess
.exec(
`node ${CLIPath} clean ${
`node ${this.$staticConfig.cliBinPath} clean ${
this.$options.dryRun ? "--dry-run" : ""
} --json --disable-analytics`,
{
Expand Down
39 changes: 25 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,23 @@ 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
);

if (process.env.NS_IS_INTERACTIVE) {
this.$keyCommandHelper.attachKeyCommands(
this.platform as IKeyCommandPlatform,
"run"
);
}
}

public async canExecute(args: string[]): Promise<boolean> {
Expand Down
19 changes: 19 additions & 0 deletions lib/commands/start.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ICommand, ICommandParameter } from "../common/definitions/commands";
import { printHeader } from "../common/header";
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> {
printHeader();
this.$startService.start();
return;
}
allowedParameters: ICommandParameter[];
async canExecute?(args: string[]): Promise<boolean> {
return true;
}
}

injector.registerCommand("start", StartCommand);
9 changes: 4 additions & 5 deletions lib/commands/typings.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IOptions } from "../declarations";
import { IOptions, IStaticConfig } from "../declarations";
import { IChildProcess, IFileSystem, IHostInfo } from "../common/declarations";
import { ICommand, ICommandParameter } from "../common/definitions/commands";
import { injector } from "../common/yok";
Expand All @@ -14,7 +14,8 @@ export class TypingsCommand implements ICommand {
private $projectData: IProjectData,
private $mobileHelper: Mobile.IMobileHelper,
private $childProcess: IChildProcess,
private $hostInfo: IHostInfo
private $hostInfo: IHostInfo,
private $staticConfig: IStaticConfig
) {}

public async execute(args: string[]): Promise<void> {
Expand Down Expand Up @@ -122,11 +123,9 @@ export class TypingsCommand implements ICommand {
path.resolve(this.$projectData.projectDir, "typings", "ios")
);

const nsPath = path.resolve(__dirname, "../../bin/nativescript.js");

await this.$childProcess.spawnFromEvent(
"node",
[nsPath, "build", "ios"],
[this.$staticConfig.cliBinPath, "build", "ios"],
"exit",
{
env: {
Expand Down
1 change: 1 addition & 0 deletions lib/common/definitions/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ declare module Config {
TRACK_FEATURE_USAGE_SETTING_NAME: string;
ERROR_REPORT_SETTING_NAME: string;
version: string;
cliBinPath: string;
getAdbFilePath(): Promise<string>;
disableAnalytics?: boolean;
disableCommandHooks?: boolean;
Expand Down
61 changes: 61 additions & 0 deletions lib/common/definitions/key-commands.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
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 IKeysUpperCase = Uppercase<IKeysLowerCase>;

export const enum SpecialKeys {
CtrlC = "\u0003",
QuestionMark = "?",
}

export type IKeysSpecial = `${SpecialKeys}`;

export type IValidKeyName = IKeysLowerCase | IKeysUpperCase | IKeysSpecial;

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

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

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

export interface IKeyCommand {
key: IValidKeyName;
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, IValidKeyName } 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: IValidKeyName, 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: IValidKeyName, resolver: any): void;
getRegisteredCommandsNames(includeDev: boolean): string[];
getRegisteredKeyCommandsNames(): string[];
dynamicCallRegex: RegExp;
dynamicCall(call: string, args?: any[]): Promise<any>;
isDefaultCommand(commandName: string): boolean;
Expand Down
37 changes: 37 additions & 0 deletions lib/common/header.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { color, stripColors } from "../color";
import { IStaticConfig } from "../declarations";
import { injector } from "./yok";

export function printHeader() {
if (process.env.HIDE_HEADER) return;

const $staticConfig: IStaticConfig = injector.resolve("$staticConfig");
const version = $staticConfig.version;

const header = [
color.dim("│ "),
color.cyanBright.bold("{N} NativeScript "),
color.whiteBright.bold("CLI"),
color.dim(` [v${version}] `),
// color.dim(" │"),
].join("");
const tagLine = [
color.dim("│ "),
color.dim(" → "),
color.whiteBright.bold("Empower JavaScript with native APIs "),
// color.dim(" │"),
].join("");

const headerLength = stripColors(header).length;
const tagLineLength = stripColors(tagLine).length;
const width = Math.max(headerLength, tagLineLength);

console.info(" " + color.dim("┌" + "─".repeat(width - 1) + "┐"));
console.info(
" " + header + " ".repeat(width - headerLength) + color.dim("│")
);
console.info(
" " + tagLine + " ".repeat(width - tagLineLength) + color.dim("│")
);
console.info(" " + color.dim("└" + "─".repeat(width - 1) + "┘"));
}
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
Loading