diff --git a/CHANGELOG.md b/CHANGELOG.md index 03059d376e..95d5556ae7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## [8.7.1](https://github.com/NativeScript/nativescript-cli/compare/v8.7.0...v8.7.1) (2024-05-16) + + +### Bug Fixes + +* **windows:** make compatible with latest node patch levels ([#5802](https://github.com/NativeScript/nativescript-cli/issues/5802)) ([8795e98](https://github.com/NativeScript/nativescript-cli/commit/8795e98e7876d11ac0032135607fb13bf00d246d)) + + +### Features + +* interactive typings generation for android ([#5798](https://github.com/NativeScript/nativescript-cli/issues/5798)) ([d3f2e70](https://github.com/NativeScript/nativescript-cli/commit/d3f2e70101d44a9bc8450c5d0b90419945c2604f)) + + + # [8.7.0](https://github.com/NativeScript/nativescript-cli/compare/v8.6.5...v8.7.0) (2024-04-08) diff --git a/lib/base-package-manager.ts b/lib/base-package-manager.ts index 22d6c6d620..12b24df7d1 100644 --- a/lib/base-package-manager.ts +++ b/lib/base-package-manager.ts @@ -111,6 +111,7 @@ export abstract class BasePackageManager implements INodePackageManager { await this.$childProcess.spawnFromEvent(npmExecutable, params, "close", { cwd: opts.cwd, stdio: stdioValue, + shell: this.$hostInfo.isWindows, }); // Whenever calling "npm install" or "yarn add" without any arguments (hence installing all dependencies) no output is emitted on stdout diff --git a/lib/commands/typings.ts b/lib/commands/typings.ts index 0f2c81028b..6856a28378 100644 --- a/lib/commands/typings.ts +++ b/lib/commands/typings.ts @@ -1,9 +1,13 @@ -import { IOptions, IStaticConfig } from "../declarations"; +import { glob } from "glob"; +import { homedir } from "os"; +import * as path from "path"; +import { PromptObject } from "prompts"; +import { color } from "../color"; import { IChildProcess, IFileSystem, IHostInfo } from "../common/declarations"; import { ICommand, ICommandParameter } from "../common/definitions/commands"; import { injector } from "../common/yok"; +import { IOptions, IStaticConfig } from "../declarations"; import { IProjectData } from "../definitions/project"; -import * as path from "path"; export class TypingsCommand implements ICommand { public allowedParameters: ICommandParameter[] = []; @@ -15,7 +19,8 @@ export class TypingsCommand implements ICommand { private $mobileHelper: Mobile.IMobileHelper, private $childProcess: IChildProcess, private $hostInfo: IHostInfo, - private $staticConfig: IStaticConfig + private $staticConfig: IStaticConfig, + private $prompter: IPrompter ) {} public async execute(args: string[]): Promise { @@ -49,8 +54,98 @@ export class TypingsCommand implements ICommand { return true; } + private async resolveGradleDependencies(target: string) { + const gradleHome = path.resolve( + process.env.GRADLE_USER_HOME ?? path.join(homedir(), `/.gradle`) + ); + const gradleFiles = path.resolve(gradleHome, "caches/modules-2/files-2.1/"); + + if (!this.$fs.exists(gradleFiles)) { + this.$logger.warn("No gradle files found"); + return; + } + + const pattern = `${target.replaceAll(":", "/")}/**/*.{jar,aar}`; + + const res = await glob(pattern, { + cwd: gradleFiles, + }); + + if (!res || res.length === 0) { + this.$logger.warn("No files found"); + return []; + } + + const items = res.map((item) => { + const [group, artifact, version, sha1, file] = item.split("/"); + return { + id: sha1 + version, + group, + artifact, + version, + sha1, + file, + path: path.resolve(gradleFiles, item), + }; + }); + + this.$logger.clearScreen(); + + const choices = await this.$prompter.promptForChoice( + `Select dependencies to generate typings for (${color.greenBright( + target + )})`, + items + .sort((a, b) => { + if (a.artifact < b.artifact) return -1; + if (a.artifact > b.artifact) return 1; + + return a.version.localeCompare(b.version, undefined, { + numeric: true, + sensitivity: "base", + }); + }) + .map((item) => { + return { + title: `${color.white(item.group)}:${color.greenBright( + item.artifact + )}:${color.yellow(item.version)} - ${color.cyanBright.bold( + item.file + )}`, + value: item.id, + }; + }), + true, + { + optionsPerPage: process.stdout.rows - 6, // 6 lines are taken up by the instructions + } as Partial + ); + + this.$logger.clearScreen(); + + return items + .filter((item) => choices.includes(item.id)) + .map((item) => item.path); + } + private async handleAndroidTypings() { - if (!(this.$options.jar || this.$options.aar)) { + const targets = this.$options.argv._.slice(2) ?? []; + const paths: string[] = []; + + if (targets.length) { + for (const target of targets) { + try { + paths.push(...(await this.resolveGradleDependencies(target))); + } catch (err) { + this.$logger.trace( + `Failed to resolve gradle dependencies for target "${target}"`, + err + ); + } + } + } + + if (!paths.length && !(this.$options.jar || this.$options.aar)) { this.$logger.warn( [ "No .jar or .aar file specified. Please specify at least one of the following:", @@ -78,7 +173,7 @@ export class TypingsCommand implements ICommand { this.$hostInfo.isWindows ? "ns.cmd" : "ns", ["prepare", "android"], "exit", - { stdio: "inherit" } + { stdio: "inherit", shell: this.$hostInfo.isWindows } ); } @@ -97,6 +192,7 @@ export class TypingsCommand implements ICommand { const inputs: string[] = [ ...asArray(this.$options.jar), ...asArray(this.$options.aar), + ...paths, ]; await this.$childProcess.spawnFromEvent( diff --git a/lib/common/mobile/android/android-virtual-device-service.ts b/lib/common/mobile/android/android-virtual-device-service.ts index 1dcba19b02..ade98318dc 100644 --- a/lib/common/mobile/android/android-virtual-device-service.ts +++ b/lib/common/mobile/android/android-virtual-device-service.ts @@ -22,7 +22,8 @@ import { import { injector } from "../../yok"; export class AndroidVirtualDeviceService - implements Mobile.IAndroidVirtualDeviceService { + implements Mobile.IAndroidVirtualDeviceService +{ private androidHome: string; private mapEmulatorIdToImageIdentifier: IStringDictionary = {}; @@ -211,7 +212,8 @@ export class AndroidVirtualDeviceService let result: ISpawnResult = null; let devices: Mobile.IDeviceInfo[] = []; let errors: string[] = []; - const canExecuteAvdManagerCommand = await this.canExecuteAvdManagerCommand(); + const canExecuteAvdManagerCommand = + await this.canExecuteAvdManagerCommand(); if (!canExecuteAvdManagerCommand) { errors = [ "Unable to execute avdmanager, ensure JAVA_HOME is set and points to correct directory", @@ -221,7 +223,8 @@ export class AndroidVirtualDeviceService if (canExecuteAvdManagerCommand) { result = await this.$childProcess.trySpawnFromCloseEvent( this.pathToAvdManagerExecutable, - ["list", "avds"] + ["list", "avds"], + { shell: this.$hostInfo.isWindows } ); } else if ( this.pathToAndroidExecutable && @@ -403,9 +406,8 @@ export class AndroidVirtualDeviceService private getAvdManagerDeviceInfo( output: string ): Mobile.IAvdManagerDeviceInfo { - const avdManagerDeviceInfo: Mobile.IAvdManagerDeviceInfo = Object.create( - null - ); + const avdManagerDeviceInfo: Mobile.IAvdManagerDeviceInfo = + Object.create(null); // Split by `\n`, not EOL as the avdmanager and android executables print results with `\n` only even on Windows _.reduce( @@ -437,9 +439,8 @@ export class AndroidVirtualDeviceService avdFilePath, AndroidVirtualDevice.CONFIG_INI_FILE_NAME ); - const configIniFileInfo = this.$androidIniFileParser.parseIniFile( - configIniFilePath - ); + const configIniFileInfo = + this.$androidIniFileParser.parseIniFile(configIniFilePath); const iniFilePath = this.getIniFilePath(configIniFileInfo, avdFilePath); const iniFileInfo = this.$androidIniFileParser.parseIniFile(iniFilePath); diff --git a/lib/services/android-plugin-build-service.ts b/lib/services/android-plugin-build-service.ts index 0ba08ec83c..84757adbd1 100644 --- a/lib/services/android-plugin-build-service.ts +++ b/lib/services/android-plugin-build-service.ts @@ -815,6 +815,7 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService { await this.$childProcess.spawnFromEvent(gradlew, localArgs, "close", { cwd: pluginBuildSettings.pluginDir, stdio: "inherit", + shell: this.$hostInfo.isWindows, }); } catch (err) { this.$errors.fail( diff --git a/lib/services/android/gradle-command-service.ts b/lib/services/android/gradle-command-service.ts index 3295433d22..3e6c3e3117 100644 --- a/lib/services/android/gradle-command-service.ts +++ b/lib/services/android/gradle-command-service.ts @@ -26,7 +26,11 @@ export class GradleCommandService implements IGradleCommandService { const { message, cwd, stdio, spawnOptions } = options; this.$logger.info(message); - const childProcessOptions = { cwd, stdio: stdio || "inherit" }; + const childProcessOptions = { + cwd, + stdio: stdio || "inherit", + shell: this.$hostInfo.isWindows, + }; const gradleExecutable = options.gradlePath ?? (this.$hostInfo.isWindows ? "gradlew.bat" : "./gradlew"); @@ -44,7 +48,7 @@ export class GradleCommandService implements IGradleCommandService { private async executeCommandSafe( gradleExecutable: string, gradleArgs: string[], - childProcessOptions: { cwd: string; stdio: string }, + childProcessOptions: { cwd: string; stdio: string; shell: boolean }, spawnOptions: ISpawnFromEventOptions ): Promise { try { diff --git a/package-lock.json b/package-lock.json index d4e5bbe597..0d76d30b6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "nativescript", - "version": "8.7.0", + "version": "8.7.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "nativescript", - "version": "8.7.0", + "version": "8.7.1", "bundleDependencies": [ "@npmcli/move-file", "stringify-package" @@ -10847,6 +10847,26 @@ "xml2js": "^0.5.0" } }, + "node_modules/parse-bmfont-xml/node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/parse-bmfont-xml/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, "node_modules/parse-conflict-json": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-3.0.1.tgz", diff --git a/package.json b/package.json index 03cba92f7b..5b58702a1e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nativescript", "preferGlobal": true, - "version": "8.7.0", + "version": "8.7.1", "author": "NativeScript ", "description": "Command-line interface for building NativeScript projects", "bin": {