nativescript 9.0.0-alpha.1 → 9.0.0-alpha.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1,16 @@
1
- {"@jsdevtools/coverage-istanbul-loader":"3.0.5","karma":"6.4.4","karma-coverage":"2.2.1","karma-nativescript-launcher":"1.0.0","mocha":"11.7.1","karma-mocha":"2.0.1","karma-chai":"0.1.0","karma-jasmine":"4.0.2","karma-qunit":"4.2.1","@types/karma-chai":"0.1.7","@types/mocha":"10.0.10","@types/jasmine":"5.1.8","@types/qunit":"2.19.12","nyc":"17.1.0"}
1
+ {
2
+ "@jsdevtools/coverage-istanbul-loader": "3.0.5",
3
+ "karma": "6.4.4",
4
+ "karma-coverage": "2.2.1",
5
+ "karma-nativescript-launcher": "1.0.0",
6
+ "mocha": "11.7.2",
7
+ "karma-mocha": "2.0.1",
8
+ "karma-chai": "0.1.0",
9
+ "karma-jasmine": "4.0.2",
10
+ "karma-qunit": "4.2.1",
11
+ "@types/karma-chai": "0.1.7",
12
+ "@types/mocha": "10.0.10",
13
+ "@types/jasmine": "5.1.9",
14
+ "@types/qunit": "2.19.13",
15
+ "nyc": "17.1.0"
16
+ }
package/lib/color.js CHANGED
@@ -1,10 +1,41 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.color = void 0;
3
+ exports.stripColors = exports.color = void 0;
4
+ const node_util_1 = require("node:util");
5
+ exports.color = {
6
+ reset: (text) => (0, node_util_1.styleText)("reset", text),
7
+ bold: (text) => (0, node_util_1.styleText)("bold", text),
8
+ dim: (text) => (0, node_util_1.styleText)("dim", text),
9
+ italic: (text) => (0, node_util_1.styleText)("italic", text),
10
+ underline: (text) => (0, node_util_1.styleText)("underline", text),
11
+ inverse: (text) => (0, node_util_1.styleText)("inverse", text),
12
+ hidden: (text) => (0, node_util_1.styleText)("hidden", text),
13
+ strikethrough: (text) => (0, node_util_1.styleText)("strikethrough", text),
14
+ black: (text) => (0, node_util_1.styleText)("black", text),
15
+ red: (text) => (0, node_util_1.styleText)("red", text),
16
+ blue: (text) => (0, node_util_1.styleText)("blue", text),
17
+ magenta: (text) => (0, node_util_1.styleText)("magenta", text),
18
+ cyan: (text) => (0, node_util_1.styleText)("cyan", text),
19
+ white: (text) => (0, node_util_1.styleText)("white", text),
20
+ gray: (text) => (0, node_util_1.styleText)("gray", text),
21
+ yellow: (text) => (0, node_util_1.styleText)("yellow", text),
22
+ green: (text) => (0, node_util_1.styleText)("green", text),
23
+ grey: (text) => (0, node_util_1.styleText)("grey", text),
24
+ bgBlack: (text) => (0, node_util_1.styleText)("bgBlack", text),
25
+ bgBlackBright: (text) => (0, node_util_1.styleText)("bgBlackBright", text),
26
+ bgRed: (text) => (0, node_util_1.styleText)("bgRed", text),
27
+ bgGreen: (text) => (0, node_util_1.styleText)("bgGreen", text),
28
+ bgYellow: (text) => (0, node_util_1.styleText)("bgYellow", text),
29
+ bgBlue: (text) => (0, node_util_1.styleText)("bgBlue", text),
30
+ bgMagenta: (text) => (0, node_util_1.styleText)("bgMagenta", text),
31
+ bgCyan: (text) => (0, node_util_1.styleText)("bgCyan", text),
32
+ bgWhite: (text) => (0, node_util_1.styleText)("bgWhite", text),
33
+ cyanBright: (text) => (0, node_util_1.styleText)("cyanBright", text),
34
+ whiteBright: (text) => (0, node_util_1.styleText)("whiteBright", text),
35
+ greenBright: (text) => (0, node_util_1.styleText)("greenBright", text),
36
+ yellowBright: (text) => (0, node_util_1.styleText)("yellowBright", text),
37
+ redBright: (text) => (0, node_util_1.styleText)("redBright", text),
38
+ styleText: node_util_1.styleText,
39
+ };
40
+ const stripColors = (text) => (0, node_util_1.stripVTControlCharacters)(text);
4
41
  exports.stripColors = stripColors;
5
- const ansi = require("ansi-colors");
6
- const chalk = require("chalk");
7
- function stripColors(formatStr) {
8
- return ansi.stripColor(formatStr);
9
- }
10
- exports.color = chalk;
@@ -69,7 +69,6 @@ class CleanCommand {
69
69
  constants.HOOKS_DIR_NAME,
70
70
  constants.PLATFORMS_DIR_NAME,
71
71
  constants.NODE_MODULES_FOLDER_NAME,
72
- constants.PACKAGE_LOCK_JSON_FILE_NAME,
73
72
  ];
74
73
  try {
75
74
  const overridePathsToClean = this.$projectConfigService.getValue("cli.pathsToClean");
@@ -166,7 +165,7 @@ class CleanCommand {
166
165
  optionsPerPage: process.stdout.rows - 6,
167
166
  });
168
167
  this.$logger.clearScreen();
169
- spinner.warn(`This will run "${color_1.color.yellow(`ns clean`)}" in all the selected projects and ${color_1.color.red.bold("delete files from your system")}!`);
168
+ spinner.warn(`This will run "${color_1.color.yellow(`ns clean`)}" in all the selected projects and ${color_1.color.styleText(["red", "bold"], "delete files from your system")}!`);
170
169
  spinner.warn(`This action cannot be undone!`);
171
170
  let confirmed = await this.$prompter.confirm("Are you sure you want to clean the selected projects?");
172
171
  if (!confirmed) {
@@ -31,7 +31,7 @@ class EmbedCommand extends prepare_1.PrepareCommand {
31
31
  const hostProjectPath = args[1];
32
32
  const resolvedHostProjectPath = this.resolveHostProjectPath(hostProjectPath);
33
33
  if (!this.$fs.exists(resolvedHostProjectPath)) {
34
- this.$logger.error(`The host project path ${color_1.color.yellow(hostProjectPath)} (resolved to: ${color_1.color.yellow.dim(resolvedHostProjectPath)}) does not exist.`);
34
+ this.$logger.error(`The host project path ${color_1.color.yellow(hostProjectPath)} (resolved to: ${color_1.color.styleText(["yellow", "dim"], resolvedHostProjectPath)}) does not exist.`);
35
35
  return;
36
36
  }
37
37
  this.$options["hostProjectPath"] = resolvedHostProjectPath;
@@ -32,10 +32,10 @@ class PostInstallCliCommand {
32
32
  }
33
33
  async postCommandAction(args) {
34
34
  this.$logger.info("");
35
- this.$logger.info(color_1.color.green.bold("You have successfully installed the NativeScript CLI!"));
35
+ this.$logger.info(color_1.color.styleText(["green", "bold"], "You have successfully installed the NativeScript CLI!"));
36
36
  this.$logger.info("");
37
37
  this.$logger.info("Your next step is to create a new project:");
38
- this.$logger.info(color_1.color.green.bold("ns create"));
38
+ this.$logger.info(color_1.color.styleText(["green", "bold"], "ns create"));
39
39
  this.$logger.info("");
40
40
  this.$logger.printMarkdown("If you have any questions, check Stack Overflow: `https://stackoverflow.com/questions/tagged/nativescript` and our public Discord channel: `https://nativescript.org/discord`");
41
41
  }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TypingsCommand = void 0;
4
- const glob_1 = require("glob");
4
+ const promises_1 = require("node:fs/promises");
5
5
  const os_1 = require("os");
6
6
  const path = require("path");
7
7
  const color_1 = require("../color");
@@ -51,16 +51,12 @@ class TypingsCommand {
51
51
  return;
52
52
  }
53
53
  const pattern = `${target.replaceAll(":", "/")}/**/*.{jar,aar}`;
54
- const res = await (0, glob_1.glob)(pattern, {
54
+ const items = [];
55
+ for await (const item of (0, promises_1.glob)(pattern, {
55
56
  cwd: gradleFiles,
56
- });
57
- if (!res || res.length === 0) {
58
- this.$logger.warn("No files found");
59
- return [];
60
- }
61
- const items = res.map((item) => {
57
+ })) {
62
58
  const [group, artifact, version, sha1, file] = item.split(path.sep);
63
- return {
59
+ items.push({
64
60
  id: sha1 + version,
65
61
  group,
66
62
  artifact,
@@ -68,8 +64,12 @@ class TypingsCommand {
68
64
  sha1,
69
65
  file,
70
66
  path: path.resolve(gradleFiles, item),
71
- };
72
- });
67
+ });
68
+ }
69
+ if (items.length === 0) {
70
+ this.$logger.warn("No files found");
71
+ return [];
72
+ }
73
73
  this.$logger.clearScreen();
74
74
  const choices = await this.$prompter.promptForChoice(`Select dependencies to generate typings for (${color_1.color.greenBright(target)})`, items
75
75
  .sort((a, b) => {
@@ -84,7 +84,7 @@ class TypingsCommand {
84
84
  })
85
85
  .map((item) => {
86
86
  return {
87
- title: `${color_1.color.white(item.group)}:${color_1.color.greenBright(item.artifact)}:${color_1.color.yellow(item.version)} - ${color_1.color.cyanBright.bold(item.file)}`,
87
+ title: `${color_1.color.white(item.group)}:${color_1.color.greenBright(item.artifact)}:${color_1.color.yellow(item.version)} - ${color_1.color.styleText(["cyanBright", "bold"], item.file)}`,
88
88
  value: item.id,
89
89
  };
90
90
  }), true, {
@@ -10,14 +10,14 @@ function printHeader() {
10
10
  const version = $staticConfig.version;
11
11
  const header = [
12
12
  color_1.color.dim("│ "),
13
- color_1.color.cyanBright.bold("{N} NativeScript "),
14
- color_1.color.whiteBright.bold("CLI"),
13
+ color_1.color.styleText(["cyanBright", "bold"], "{N} NativeScript "),
14
+ color_1.color.styleText(["whiteBright", "bold"], "CLI"),
15
15
  color_1.color.dim(` [v${version}] `),
16
16
  ].join("");
17
17
  const tagLine = [
18
18
  color_1.color.dim("│ "),
19
19
  color_1.color.dim(" → "),
20
- color_1.color.whiteBright.bold("Empower JavaScript with native APIs "),
20
+ color_1.color.styleText(["whiteBright", "bold"], "Empower JavaScript with native APIs "),
21
21
  ].join("");
22
22
  const headerLength = (0, color_1.stripColors)(header).length;
23
23
  const tagLineLength = (0, color_1.stripColors)(tagLine).length;
@@ -19,7 +19,7 @@ function layout(config) {
19
19
  return msg;
20
20
  }
21
21
  if (logEvent.level.isEqualTo(constants_1.LoggerLevel.ERROR)) {
22
- return color_1.color.red.bold(msg);
22
+ return color_1.color.styleText(["red", "bold"], msg);
23
23
  }
24
24
  if (logEvent.level.isEqualTo(constants_1.LoggerLevel.WARN)) {
25
25
  return color_1.color.yellow(msg);
@@ -110,8 +110,8 @@ class Logger {
110
110
  const opts = {
111
111
  unescape: true,
112
112
  link: color_1.color.red,
113
- strong: color_1.color.green.bold,
114
- firstHeading: color_1.color.blue.bold,
113
+ strong: (str) => color_1.color.styleText(["green", "bold"], str),
114
+ firstHeading: (str) => color_1.color.styleText(["blue", "bold"], str),
115
115
  tableOptions: {
116
116
  chars: { mid: "", "left-mid": "", "mid-mid": "", "right-mid": "" },
117
117
  style: {
@@ -37,14 +37,16 @@ class AndroidEmulatorServices {
37
37
  async getRunningEmulatorName(emulatorId) {
38
38
  let result = await this.$androidVirtualDeviceService.getRunningEmulatorName(emulatorId);
39
39
  if (!result) {
40
- result = await this.$androidGenymotionService.getRunningEmulatorName(emulatorId);
40
+ result =
41
+ await this.$androidGenymotionService.getRunningEmulatorName(emulatorId);
41
42
  }
42
43
  return result;
43
44
  }
44
45
  async getRunningEmulatorImageIdentifier(emulatorId) {
45
46
  let result = await this.$androidVirtualDeviceService.getRunningEmulatorImageIdentifier(emulatorId);
46
47
  if (!result) {
47
- result = await this.$androidGenymotionService.getRunningEmulatorImageIdentifier(emulatorId);
48
+ result =
49
+ await this.$androidGenymotionService.getRunningEmulatorImageIdentifier(emulatorId);
48
50
  }
49
51
  return result;
50
52
  }
@@ -116,13 +118,13 @@ class AndroidEmulatorServices {
116
118
  let pathToEmulatorExecutable = null;
117
119
  let startEmulatorArgs = null;
118
120
  if (emulator.vendor === constants_1.AndroidVirtualDevice.AVD_VENDOR_NAME) {
119
- pathToEmulatorExecutable = this.$androidVirtualDeviceService
120
- .pathToEmulatorExecutable;
121
+ pathToEmulatorExecutable =
122
+ this.$androidVirtualDeviceService.pathToEmulatorExecutable;
121
123
  startEmulatorArgs = this.$androidVirtualDeviceService.startEmulatorArgs(emulator.imageIdentifier);
122
124
  }
123
125
  else if (emulator.vendor === constants_1.AndroidVirtualDevice.GENYMOTION_VENDOR_NAME) {
124
- pathToEmulatorExecutable = this.$androidGenymotionService
125
- .pathToEmulatorExecutable;
126
+ pathToEmulatorExecutable =
127
+ this.$androidGenymotionService.pathToEmulatorExecutable;
126
128
  startEmulatorArgs = this.$androidGenymotionService.startEmulatorArgs(emulator.imageIdentifier);
127
129
  }
128
130
  this.$logger.info(`Starting Android emulator with image ${emulator.imageIdentifier}`);
@@ -146,7 +148,7 @@ class AndroidEmulatorServices {
146
148
  }
147
149
  const minVersion = semver.coerce(constants_1.AndroidVirtualDevice.MIN_ANDROID_VERSION);
148
150
  const bestVersion = best && best.version && semver.coerce(best.version);
149
- return bestVersion && semver.gte(bestVersion, minVersion) ? best : null;
151
+ return !bestVersion || semver.gte(bestVersion, minVersion) ? best : null;
150
152
  }
151
153
  async waitForEmulatorBootToComplete(emulator, endTimeEpoch, timeout) {
152
154
  this.$logger.info("Waiting for emulator device initialization...", {
@@ -25,13 +25,12 @@ class DeviceLogProvider extends device_log_provider_base_1.DeviceLogProviderBase
25
25
  };
26
26
  this.deviceColorMap = new Map();
27
27
  this.colorPool = [
28
- "bgBlackBright",
29
- "bgMagentaBright",
28
+ "bgGray",
30
29
  "bgBlueBright",
31
30
  "bgWhiteBright",
32
31
  "bgCyanBright",
33
32
  "bgYellowBright",
34
- "bgGreenBright",
33
+ "bgMagentaBright",
35
34
  ];
36
35
  this.colorPoolIndex = 0;
37
36
  }
@@ -113,7 +112,7 @@ class DeviceLogProvider extends device_log_provider_base_1.DeviceLogProviderBase
113
112
  .join("")
114
113
  .trimEnd();
115
114
  toLog.split("\n").forEach((actualLine) => {
116
- this.printLine(color_1.color[this.getDeviceColor(deviceIdentifier)](" "), this.consoleLevelColor[level](actualLine));
115
+ this.printLine(color_1.color.styleText(this.getDeviceColor(deviceIdentifier), " "), this.consoleLevelColor[level](actualLine));
117
116
  });
118
117
  }
119
118
  }
@@ -7,6 +7,7 @@ const yok_1 = require("../yok");
7
7
  class EmulatorHelper {
8
8
  constructor() {
9
9
  this.mapAndroidApiLevelToVersion = {
10
+ "android-36": "16.0.0",
10
11
  "android-35": "15.0.0",
11
12
  "android-34": "14.0.0",
12
13
  "android-33": "13.0.0",
@@ -93,24 +93,38 @@ class HooksService {
93
93
  }
94
94
  return _.flatten(results);
95
95
  }
96
+ isESModule(hook) {
97
+ const ext = path.extname(hook.fullPath).toLowerCase();
98
+ return ext === ".mjs";
99
+ }
96
100
  async executeHook(directoryPath, hookName, hook, hookArguments) {
97
101
  hookArguments = hookArguments || {};
98
102
  let result;
99
103
  const relativePath = path.relative(directoryPath, hook.fullPath);
100
104
  const trackId = relativePath.replace(new RegExp("\\" + path.sep, "g"), constants_1.AnalyticsEventLabelDelimiter);
105
+ const isESM = this.isESModule(hook);
101
106
  let command = this.getSheBangInterpreter(hook);
102
107
  let inProc = false;
103
108
  if (!command) {
104
109
  command = hook.fullPath;
105
- if ([".mjs", ".js"].includes(path.extname(hook.fullPath).toLowerCase())) {
110
+ if ([".mjs", ".cjs", ".js"].includes(path.extname(hook.fullPath).toLowerCase())) {
106
111
  command = process.argv[0];
107
- inProc = this.shouldExecuteInProcess(this.$fs.readText(hook.fullPath));
112
+ inProc = isESM
113
+ ? true
114
+ : this.shouldExecuteInProcess(this.$fs.readText(hook.fullPath));
108
115
  }
109
116
  }
110
117
  const startTime = this.$performanceService.now();
111
118
  if (inProc) {
112
119
  this.$logger.trace("Executing %s hook at location %s in-process", hookName, hook.fullPath);
113
- const hookEntryPoint = require(hook.fullPath);
120
+ let hookEntryPoint;
121
+ if (isESM) {
122
+ const { default: hookFn } = await Promise.resolve(`${hook.fullPath}`).then(s => require(s));
123
+ hookEntryPoint = hookFn;
124
+ }
125
+ else {
126
+ hookEntryPoint = require(hook.fullPath);
127
+ }
114
128
  this.$logger.trace(`Validating ${hookName} arguments.`);
115
129
  const invalidArguments = this.validateHookArguments(hookEntryPoint, hook.fullPath);
116
130
  if (invalidArguments.length) {
@@ -119,7 +133,8 @@ class HooksService {
119
133
  }
120
134
  const projectDataHookArg = hookArguments["hookArgs"] && hookArguments["hookArgs"]["projectData"];
121
135
  if (projectDataHookArg) {
122
- hookArguments["projectData"] = hookArguments["$projectData"] = projectDataHookArg;
136
+ hookArguments["projectData"] = hookArguments["$projectData"] =
137
+ projectDataHookArg;
123
138
  }
124
139
  const maybePromise = this.$injector.resolve(hookEntryPoint, hookArguments);
125
140
  if (maybePromise) {
@@ -215,9 +230,11 @@ class HooksService {
215
230
  prepareEnvironment(hookFullPath) {
216
231
  const clientName = this.$staticConfig.CLIENT_NAME.toUpperCase();
217
232
  const environment = {};
218
- environment[util.format("%s-COMMANDLINE", clientName)] = process.argv.join(" ");
233
+ environment[util.format("%s-COMMANDLINE", clientName)] =
234
+ process.argv.join(" ");
219
235
  environment[util.format("%s-HOOK_FULL_PATH", clientName)] = hookFullPath;
220
- environment[util.format("%s-VERSION", clientName)] = this.$staticConfig.version;
236
+ environment[util.format("%s-VERSION", clientName)] =
237
+ this.$staticConfig.version;
221
238
  return {
222
239
  cwd: this.$projectHelper.projectDir,
223
240
  stdio: "inherit",
@@ -28,7 +28,7 @@ function verifyNodeVersion() {
28
28
  if (versionsCausingFailure.indexOf(nodeVer) !== -1 ||
29
29
  !semver.valid(nodeVer) ||
30
30
  semver.lt(nodeVer, minimumRequiredVersion)) {
31
- console.error(color_1.color.red.bold(util.format("%sNode.js '%s' is not supported. To be able to work with %s CLI, install any Node.js version in the following range: %s.%s", os.EOL, nodeVer, cliName, supportedVersionsRange, os.EOL)));
31
+ console.error(color_1.color.bold(color_1.color.red(util.format("%sNode.js '%s' is not supported. To be able to work with %s CLI, install any Node.js version in the following range: %s.%s", os.EOL, nodeVer, cliName, supportedVersionsRange, os.EOL))));
32
32
  process.exit(1);
33
33
  }
34
34
  }
@@ -10,7 +10,8 @@ const simple_git_1 = require("simple-git");
10
10
  const update_controller_base_1 = require("./update-controller-base");
11
11
  const helpers_1 = require("../common/helpers");
12
12
  const yok_1 = require("../common/yok");
13
- const temp = require("temp");
13
+ const fs = require("fs");
14
+ const os_1 = require("os");
14
15
  const color_1 = require("../color");
15
16
  class MigrateController extends update_controller_base_1.UpdateControllerBase {
16
17
  constructor($fs, $platformCommandHelper, $platformsDataService, $packageInstallationManager, $packageManager, $pacoteService, $logger, $errors, $pluginsService, $projectDataService, $projectConfigService, $options, $resources, $injector, $settingsService, $staticConfig, $terminalSpinnerService, $projectCleanupService, $projectBackupService, $childProcess) {
@@ -710,9 +711,7 @@ class MigrateController extends update_controller_base_1.UpdateControllerBase {
710
711
  if (polyfillsPath) {
711
712
  return "./" + path.relative(projectDir, polyfillsPath);
712
713
  }
713
- const tempDir = temp.mkdirSync({
714
- prefix: "migrate-angular-polyfills",
715
- });
714
+ const tempDir = fs.mkdtempSync(path.join((0, os_1.tmpdir)(), "migrate-angular-polyfills-"));
716
715
  await this.$pacoteService.extractPackage(constants.RESERVED_TEMPLATE_NAMES["angular"], tempDir);
717
716
  this.$fs.copyFile(path.resolve(tempDir, "src/polyfills.ts"), possiblePaths[0]);
718
717
  this.$fs.deleteDirectory(tempDir);
@@ -1,9 +1,13 @@
1
- import { AffixOptions } from "temp";
1
+ export type AffixOptions = {
2
+ prefix?: string;
3
+ suffix?: string;
4
+ dir?: string;
5
+ };
2
6
 
3
7
  /**
4
8
  * Declares wrapped functions of temp module
5
9
  */
6
- interface ITempService {
10
+ export interface ITempService {
7
11
  mkdirSync(affixes: string | AffixOptions): Promise<string>;
8
12
  path(options: string | AffixOptions): Promise<string>;
9
13
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const color_1 = require("../color");
4
+ const node_util_1 = require("node:util");
4
5
  const yok_1 = require("../common/yok");
5
6
  class KeyCommandHelper {
6
7
  constructor() {
@@ -33,7 +34,7 @@ class KeyCommandHelper {
33
34
  }
34
35
  if (keyCommand.key !== "\u0003") {
35
36
  const line = ` ${color_1.color.dim("→")} ${color_1.color.bold(keyCommand.key)} — ${keyCommand.description}`;
36
- const lineLength = (0, color_1.stripColors)(line).length - 1;
37
+ const lineLength = (0, node_util_1.stripVTControlCharacters)(line).length - 1;
37
38
  console.log(color_1.color.dim(` ┌${"─".repeat(lineLength)}┐`));
38
39
  console.log(line + color_1.color.dim(" │"));
39
40
  console.log(color_1.color.dim(` └${"─".repeat(lineLength)}┘`));
@@ -29,7 +29,8 @@ class AnalyticsSettingsService {
29
29
  return this.getSettingValueOrDefault(this.$staticConfig.ANALYTICS_INSTALLATION_ID_SETTING_NAME);
30
30
  }
31
31
  getClientName() {
32
- return "" + color_1.color.cyan.bold(this.$staticConfig.CLIENT_NAME_ALIAS);
32
+ return ("" +
33
+ color_1.color.styleText(["cyan", "bold"], this.$staticConfig.CLIENT_NAME_ALIAS));
33
34
  }
34
35
  async getUserSessionsCount(projectName) {
35
36
  const sessionsCountForProject = await this.$userSettingsService.getSettingValue(this.getSessionsProjectKey(projectName));
@@ -15,6 +15,7 @@ const decorators_1 = require("../../common/decorators");
15
15
  const constants_1 = require("../../constants");
16
16
  const yok_1 = require("../../common/yok");
17
17
  const package_path_helper_1 = require("../../helpers/package-path-helper");
18
+ const debugLog = false;
18
19
  class BundlerCompilerService extends events_1.EventEmitter {
19
20
  constructor($options, $errors, $childProcess, $fs, $hooksService, $hostInfo, $logger, $mobileHelper, $cleanupService, $packageManager, $packageInstallationManager, $projectConfigService) {
20
21
  super();
@@ -43,6 +44,7 @@ class BundlerCompilerService extends events_1.EventEmitter {
43
44
  prepareData.watch = true;
44
45
  try {
45
46
  const childProcess = await this.startBundleProcess(platformData, projectData, prepareData);
47
+ const isVite = this.getBundler() === "vite";
46
48
  childProcess.stdout.on("data", function (data) {
47
49
  process.stdout.write(data);
48
50
  });
@@ -51,6 +53,98 @@ class BundlerCompilerService extends events_1.EventEmitter {
51
53
  });
52
54
  childProcess.on("message", (message) => {
53
55
  this.$logger.trace(`Message from ${projectData.bundler}`, message);
56
+ if (isVite &&
57
+ message &&
58
+ message.emittedFiles) {
59
+ message = message;
60
+ if (debugLog) {
61
+ console.log("Received Vite IPC message:", message);
62
+ }
63
+ const distOutput = path.join(projectData.projectDir, "dist");
64
+ const destDir = path.join(platformData.appDestinationDirectoryPath, this.$options.hostProjectModuleName);
65
+ if (debugLog) {
66
+ console.log(`🔥 Copying from ${distOutput} to ${destDir}`);
67
+ }
68
+ if (message.isHMR) {
69
+ if (debugLog) {
70
+ console.log("🔥 HMR update - copying only changed files for:", message.changedFiles);
71
+ }
72
+ let filesToCopy = message.emittedFiles;
73
+ const hasHTMLChanges = message.changedFiles.some((f) => f.endsWith(".html"));
74
+ if (hasHTMLChanges) {
75
+ filesToCopy = message.emittedFiles.filter((f) => f.includes(".component") ||
76
+ f === "bundle.mjs" ||
77
+ f === "bundle.mjs.map");
78
+ if (debugLog) {
79
+ console.log("🔥 HTML change detected - copying component files:", filesToCopy);
80
+ }
81
+ }
82
+ this.copyViteBundleToNative(distOutput, destDir, filesToCopy);
83
+ }
84
+ else if (message.buildType === "incremental" &&
85
+ message.changedFiles &&
86
+ message.changedFiles.length > 0) {
87
+ if (debugLog) {
88
+ console.log("🔥 Incremental build - copying only relevant files for:", message.changedFiles);
89
+ }
90
+ const filesToCopy = this.getIncrementalFilesToCopy(message.emittedFiles, message.changedFiles);
91
+ if (debugLog) {
92
+ console.log("🔥 Incremental build - files to copy:", filesToCopy);
93
+ }
94
+ this.copyViteBundleToNative(distOutput, destDir, filesToCopy);
95
+ }
96
+ else if (message.buildType === "incremental" &&
97
+ message.changedFiles &&
98
+ message.changedFiles.length > 0) {
99
+ console.log("🔥 Incremental build - copying only relevant files for:", message.changedFiles);
100
+ const filesToCopy = this.getIncrementalFilesToCopy(message.emittedFiles, message.changedFiles);
101
+ console.log("🔥 Incremental build - files to copy:", filesToCopy);
102
+ this.copyViteBundleToNative(distOutput, destDir, filesToCopy);
103
+ }
104
+ else {
105
+ if (debugLog) {
106
+ console.log("🔥 Full build - copying all files");
107
+ }
108
+ this.copyViteBundleToNative(distOutput, destDir);
109
+ }
110
+ if (isFirstBundlerWatchCompilation) {
111
+ isFirstBundlerWatchCompilation = false;
112
+ if (debugLog) {
113
+ console.log("Vite first build completed, resolving compileWithWatch");
114
+ }
115
+ resolve(childProcess);
116
+ }
117
+ const files = message.emittedFiles.map((file) => path.join(platformData.appDestinationDirectoryPath, this.$options.hostProjectModuleName, file));
118
+ const data = {
119
+ files,
120
+ hasOnlyHotUpdateFiles: message.isHMR || false,
121
+ hmrData: {
122
+ hash: message.hash || "",
123
+ fallbackFiles: [],
124
+ },
125
+ platform: platformData.platformNameLowerCase,
126
+ };
127
+ this.$logger.info(`Vite build completed! Files copied to native platform.`);
128
+ this.notifyHMRClients({
129
+ type: message.isHMR ? "js-update" : "build-complete",
130
+ timestamp: Date.now(),
131
+ changedFiles: message.changedFiles || [],
132
+ buildType: message.buildType || "incremental",
133
+ isHMR: message.isHMR || false,
134
+ });
135
+ if (message.isHMR) {
136
+ if (debugLog) {
137
+ console.log("🔥 Skipping BUNDLER_COMPILATION_COMPLETE for HMR update - app will not restart");
138
+ }
139
+ }
140
+ else {
141
+ if (debugLog) {
142
+ console.log("🔥 Emitting BUNDLER_COMPILATION_COMPLETE for full build");
143
+ }
144
+ this.emit(constants_1.BUNDLER_COMPILATION_COMPLETE, data);
145
+ }
146
+ return;
147
+ }
54
148
  if (typeof message === "object" &&
55
149
  "version" in message &&
56
150
  "type" in message) {
@@ -114,19 +208,6 @@ class BundlerCompilerService extends events_1.EventEmitter {
114
208
  childProcess.on("close", async (arg) => {
115
209
  const exitCode = typeof arg === "number" ? arg : arg && arg.code;
116
210
  this.$logger.trace(`${capitalizeFirstLetter(projectData.bundler)} process exited with code ${exitCode} when we expected it to be long living with watch.`);
117
- if (this.getBundler() === "vite" && exitCode === 0) {
118
- const bundlePath = path.join(projectData.projectDir, "dist/bundle.js");
119
- console.log("bundlePath:", bundlePath);
120
- const data = {
121
- files: [bundlePath],
122
- hasOnlyHotUpdateFiles: false,
123
- hmrData: {},
124
- platform: platformData.platformNameLowerCase,
125
- };
126
- this.emit(constants_1.BUNDLER_COMPILATION_COMPLETE, data);
127
- resolve(1);
128
- return;
129
- }
130
211
  await this.$cleanupService.removeKillProcess(childProcess.pid.toString());
131
212
  const error = new Error(`Executing ${projectData.bundler} failed with exit code ${exitCode}.`);
132
213
  error.code = exitCode;
@@ -200,9 +281,15 @@ class BundlerCompilerService extends events_1.EventEmitter {
200
281
  }
201
282
  const envData = this.buildEnvData(platformData.platformNameLowerCase, projectData, prepareData);
202
283
  const isVite = this.getBundler() === "vite";
284
+ const cliArgs = await this.buildEnvCommandLineParams(envData, platformData, projectData, prepareData);
203
285
  const envParams = isVite
204
- ? [`--mode=${platformData.platformNameLowerCase}`]
205
- : await this.buildEnvCommandLineParams(envData, platformData, projectData, prepareData);
286
+ ? [
287
+ `--mode=${prepareData.release ? "production" : "development"}`,
288
+ `--watch`,
289
+ "--",
290
+ ...cliArgs,
291
+ ]
292
+ : cliArgs;
206
293
  const additionalNodeArgs = semver.major(process.version) <= 8 ? ["--harmony"] : [];
207
294
  if (await this.shouldUsePreserveSymlinksOption()) {
208
295
  additionalNodeArgs.push("--preserve-symlinks");
@@ -213,7 +300,7 @@ class BundlerCompilerService extends events_1.EventEmitter {
213
300
  const args = [
214
301
  ...additionalNodeArgs,
215
302
  this.getBundlerExecutablePath(projectData),
216
- this.isModernBundler(projectData) ? `build` : null,
303
+ isVite ? "build" : this.isModernBundler(projectData) ? `build` : null,
217
304
  `--config=${projectData.bundlerConfigPath}`,
218
305
  ...envParams,
219
306
  ].filter(Boolean);
@@ -222,7 +309,7 @@ class BundlerCompilerService extends events_1.EventEmitter {
222
309
  args.push("--watch");
223
310
  }
224
311
  }
225
- const stdio = prepareData.watch ? ["ipc"] : "inherit";
312
+ const stdio = prepareData.watch || isVite ? ["ipc"] : "inherit";
226
313
  const options = {
227
314
  cwd: projectData.projectDir,
228
315
  stdio,
@@ -242,7 +329,9 @@ class BundlerCompilerService extends events_1.EventEmitter {
242
329
  USER_PROJECT_PLATFORMS_IOS: this.$options.hostProjectPath,
243
330
  });
244
331
  }
245
- console.log("args:", args);
332
+ if (debugLog) {
333
+ console.log("args:", args);
334
+ }
246
335
  const childProcess = this.$childProcess.spawn(process.execPath, args, options);
247
336
  this.bundlerProcesses[platformData.platformNameLowerCase] = childProcess;
248
337
  await this.$cleanupService.addKillProcess(childProcess.pid.toString());
@@ -439,6 +528,108 @@ class BundlerCompilerService extends events_1.EventEmitter {
439
528
  getBundler() {
440
529
  return this.$projectConfigService.getValue(`bundler`, "webpack");
441
530
  }
531
+ copyViteBundleToNative(distOutput, destDir, specificFiles = null) {
532
+ if (debugLog) {
533
+ console.log(`Copying Vite bundle from "${distOutput}" to "${destDir}"`);
534
+ }
535
+ const fs = require("fs");
536
+ try {
537
+ if (specificFiles) {
538
+ if (debugLog) {
539
+ console.log("🔥 Selective copy - copying specific files:", specificFiles);
540
+ }
541
+ fs.mkdirSync(destDir, { recursive: true });
542
+ for (const file of specificFiles) {
543
+ const srcPath = path.join(distOutput, file);
544
+ const destPath = path.join(destDir, file);
545
+ if (!fs.existsSync(srcPath))
546
+ continue;
547
+ fs.mkdirSync(path.dirname(destPath), { recursive: true });
548
+ fs.copyFileSync(srcPath, destPath);
549
+ if (debugLog) {
550
+ console.log(`🔥 Copied ${file}`);
551
+ }
552
+ }
553
+ }
554
+ else {
555
+ if (debugLog) {
556
+ console.log("🔥 Full build: Copying all files");
557
+ }
558
+ if (fs.existsSync(destDir)) {
559
+ fs.rmSync(destDir, { recursive: true, force: true });
560
+ }
561
+ fs.mkdirSync(destDir, { recursive: true });
562
+ if (fs.existsSync(distOutput)) {
563
+ this.copyRecursiveSync(distOutput, destDir, fs);
564
+ }
565
+ else {
566
+ this.$logger.warn(`Vite output directory does not exist: ${distOutput}`);
567
+ }
568
+ }
569
+ }
570
+ catch (error) {
571
+ this.$logger.warn(`Failed to copy Vite bundle: ${error.message}`);
572
+ }
573
+ }
574
+ getIncrementalFilesToCopy(emittedFiles, changedFiles) {
575
+ const filesToCopy = [];
576
+ const bundleFiles = emittedFiles.filter((file) => !file.includes("vendor") &&
577
+ (file.includes("bundle") ||
578
+ file.includes("main") ||
579
+ file.includes("app") ||
580
+ file.endsWith(".mjs") ||
581
+ file.endsWith(".js")));
582
+ filesToCopy.push(...bundleFiles);
583
+ const sourceMapFiles = emittedFiles.filter((file) => !file.includes("vendor") && file.endsWith(".map"));
584
+ filesToCopy.push(...sourceMapFiles);
585
+ const hasAssetChanges = changedFiles.some((file) => file.includes("/assets/") ||
586
+ file.includes("/static/") ||
587
+ file.includes("/public/"));
588
+ if (hasAssetChanges) {
589
+ const assetFiles = emittedFiles.filter((file) => file.includes("assets/") ||
590
+ file.includes("static/") ||
591
+ file.includes("fonts/") ||
592
+ file.includes("images/"));
593
+ filesToCopy.push(...assetFiles);
594
+ }
595
+ return [...new Set(filesToCopy)];
596
+ }
597
+ notifyHMRClients(message) {
598
+ try {
599
+ const WebSocket = require("ws");
600
+ const ws = new WebSocket("ws://localhost:24678");
601
+ ws.on("open", () => {
602
+ if (debugLog) {
603
+ console.log("🔥 Sending HMR notification to bridge:", message.type);
604
+ }
605
+ ws.send(JSON.stringify(message));
606
+ ws.close();
607
+ });
608
+ ws.on("error", () => {
609
+ if (debugLog) {
610
+ console.log("🔥 HMR bridge not available (this is normal without HMR)");
611
+ }
612
+ });
613
+ }
614
+ catch (error) {
615
+ if (debugLog) {
616
+ console.log("🔥 WebSocket not available for HMR notifications");
617
+ }
618
+ }
619
+ }
620
+ copyRecursiveSync(src, dest, fs) {
621
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
622
+ const srcPath = path.join(src, entry.name);
623
+ const destPath = path.join(dest, entry.name);
624
+ if (entry.isDirectory()) {
625
+ fs.mkdirSync(destPath, { recursive: true });
626
+ this.copyRecursiveSync(srcPath, destPath, fs);
627
+ }
628
+ else if (entry.isFile() || entry.isSymbolicLink()) {
629
+ fs.copyFileSync(srcPath, destPath);
630
+ }
631
+ }
632
+ }
442
633
  }
443
634
  exports.BundlerCompilerService = BundlerCompilerService;
444
635
  __decorate([
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SPMService = void 0;
4
4
  const yok_1 = require("../../common/yok");
5
- const trapezedev_project_1 = require("@rigor789/trapezedev-project");
5
+ const trapezedev_project_1 = require("@nstudio/trapezedev-project");
6
6
  const path = require("path");
7
7
  class SPMService {
8
8
  constructor($logger, $projectConfigService, $xcodebuildCommandService, $xcodebuildArgsService) {
@@ -292,7 +292,9 @@ class AndroidLivesyncTool {
292
292
  socket.removeAllListeners();
293
293
  this.pendingConnectionData.socketTimer = setTimeout(tryConnect, 1000);
294
294
  };
295
- this.pendingConnectionData.socket = socket;
295
+ if (this.pendingConnectionData) {
296
+ this.pendingConnectionData.socket = socket;
297
+ }
296
298
  socket.once("data", (data) => {
297
299
  socket.removeListener("close", tryConnectAfterTimeout);
298
300
  socket.removeListener("error", tryConnectAfterTimeout);
@@ -1,20 +1,32 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TempService = void 0;
4
- const temp = require("temp");
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+ const os_1 = require("os");
5
7
  const yok_1 = require("../common/yok");
6
8
  class TempService {
7
9
  constructor($cleanupService) {
8
10
  this.$cleanupService = $cleanupService;
9
- temp.track();
10
11
  }
11
12
  async mkdirSync(affixes) {
12
- const pathToDir = temp.mkdirSync(affixes);
13
+ var _a;
14
+ const opts = typeof affixes === "string" ? { prefix: affixes } : affixes;
15
+ const baseDir = (opts === null || opts === void 0 ? void 0 : opts.dir) ? opts.dir : (0, os_1.tmpdir)();
16
+ const prefix = ((_a = opts === null || opts === void 0 ? void 0 : opts.prefix) !== null && _a !== void 0 ? _a : "ns-").replace(/\s+/g, "-");
17
+ const pathToDir = fs.mkdtempSync(path.join(baseDir, prefix));
13
18
  await this.$cleanupService.addCleanupDeleteAction(pathToDir);
14
19
  return pathToDir;
15
20
  }
16
21
  async path(options) {
17
- const pathToFile = temp.path(options);
22
+ var _a, _b;
23
+ const opts = typeof options === "string" ? { prefix: options } : options;
24
+ const baseDir = (opts === null || opts === void 0 ? void 0 : opts.dir) ? opts.dir : (0, os_1.tmpdir)();
25
+ const prefix = ((_a = opts === null || opts === void 0 ? void 0 : opts.prefix) !== null && _a !== void 0 ? _a : "ns-").replace(/\s+/g, "-");
26
+ const suffix = (_b = opts === null || opts === void 0 ? void 0 : opts.suffix) !== null && _b !== void 0 ? _b : "";
27
+ const unique = Math.random().toString(36).slice(2);
28
+ const filePath = path.join(baseDir, `${prefix}${unique}${suffix}`);
29
+ const pathToFile = filePath;
18
30
  await this.$cleanupService.addCleanupDeleteAction(pathToFile);
19
31
  return pathToFile;
20
32
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nativescript",
3
3
  "main": "./lib/nativescript-cli-lib.js",
4
- "version": "9.0.0-alpha.1",
4
+ "version": "9.0.0-alpha.11",
5
5
  "author": "NativeScript <oss@nativescript.org>",
6
6
  "description": "Command-line interface for building NativeScript projects",
7
7
  "bin": {
@@ -51,19 +51,17 @@
51
51
  "keywords": [
52
52
  "nativescript",
53
53
  "typescript",
54
- "mobile"
54
+ "javascript"
55
55
  ],
56
56
  "dependencies": {
57
- "@foxt/js-srp": "^0.0.3-patch2",
58
- "@nativescript/doctor": "2.0.16-rc.0",
59
- "@npmcli/arborist": "^9.0.0",
57
+ "@foxt/js-srp": "0.0.3-patch2",
58
+ "@nativescript/doctor": "2.0.17",
59
+ "@npmcli/arborist": "9.1.4",
60
60
  "@rigor789/resolve-package-path": "1.0.7",
61
- "@rigor789/trapezedev-project": "7.1.2",
62
- "ansi-colors": "^4.1.3",
63
- "archiver": "^7.0.1",
64
- "axios": "1.7.9",
61
+ "@nstudio/trapezedev-project": "7.2.3",
62
+ "archiver": "7.0.1",
63
+ "axios": "1.11.0",
65
64
  "byline": "5.0.0",
66
- "chalk": "4.1.2",
67
65
  "chokidar": "4.0.3",
68
66
  "cli-table3": "0.6.5",
69
67
  "color": "4.2.3",
@@ -72,16 +70,15 @@
72
70
  "email-validator": "2.0.4",
73
71
  "esprima": "4.0.1",
74
72
  "font-finder": "1.1.0",
75
- "glob": "11.0.1",
76
73
  "ios-device-lib": "0.9.4",
77
74
  "ios-mobileprovision-finder": "1.2.1",
78
- "ios-sim-portable": "4.5.0",
75
+ "ios-sim-portable": "4.5.1",
79
76
  "jimp": "1.6.0",
80
77
  "lodash": "4.17.21",
81
78
  "log4js": "6.9.1",
82
- "marked": "15.0.7",
79
+ "marked": "15.0.12",
83
80
  "marked-terminal": "7.3.0",
84
- "minimatch": "10.0.1",
81
+ "minimatch": "10.0.3",
85
82
  "mkdirp": "3.0.1",
86
83
  "mute-stream": "2.0.0",
87
84
  "nativescript-dev-xcode": "0.8.1",
@@ -91,37 +88,35 @@
91
88
  "pbxproj-dom": "1.2.0",
92
89
  "plist": "3.1.0",
93
90
  "plist-merge-patch": "0.2.0",
94
- "prettier": "3.5.2",
91
+ "prettier": "3.6.2",
95
92
  "prompts": "2.4.2",
96
93
  "proper-lockfile": "4.1.2",
97
- "proxy-lib": "0.4.0",
94
+ "proxy-lib": "0.4.1",
98
95
  "qr-image": "3.2.0",
99
96
  "qrcode-terminal": "0.12.0",
100
- "semver": "7.7.1",
101
- "shelljs": "0.8.5",
97
+ "semver": "7.7.2",
98
+ "shelljs": "0.10.0",
102
99
  "simple-git": "3.27.0",
103
100
  "simple-plist": "1.4.0",
104
- "source-map": "0.7.4",
101
+ "source-map": "0.7.6",
105
102
  "tar": "7.4.3",
106
- "temp": "0.9.4",
107
103
  "ts-morph": "25.0.1",
108
104
  "tunnel": "0.0.6",
109
105
  "typescript": "5.7.3",
110
106
  "universal-analytics": "0.5.3",
111
107
  "uuid": "11.1.0",
112
108
  "winreg": "1.2.5",
113
- "ws": "8.18.1",
109
+ "ws": "8.18.3",
114
110
  "xml2js": "0.6.2",
115
111
  "yargs": "17.7.2"
116
112
  },
117
113
  "devDependencies": {
118
114
  "@types/archiver": "^6.0.3",
119
115
  "@types/byline": "^4.2.36",
120
- "@types/chai": "5.0.1",
121
- "@types/chai-as-promised": "8.0.1",
116
+ "@types/chai": "5.2.2",
117
+ "@types/chai-as-promised": "8.0.2",
122
118
  "@types/color": "4.2.0",
123
119
  "@types/convert-source-map": "2.0.3",
124
- "@types/glob": "^8.1.0",
125
120
  "@types/lodash": "4.17.15",
126
121
  "@types/marked-terminal": "^6.1.1",
127
122
  "@types/node": "^22.0.0",
@@ -132,20 +127,20 @@
132
127
  "@types/proper-lockfile": "4.1.4",
133
128
  "@types/qr-image": "3.2.9",
134
129
  "@types/retry": "0.12.5",
135
- "@types/semver": "7.5.8",
130
+ "@types/semver": "7.7.1",
136
131
  "@types/shelljs": "^0.8.11",
137
132
  "@types/sinon": "^17.0.3",
138
133
  "@types/tabtab": "^3.0.2",
139
134
  "@types/tar": "6.1.13",
140
- "@types/temp": "0.9.4",
141
135
  "@types/tunnel": "0.0.7",
142
136
  "@types/universal-analytics": "0.4.8",
143
137
  "@types/uuid": "^10.0.0",
144
- "@types/ws": "8.5.14",
138
+ "@types/ws": "8.18.1",
145
139
  "@types/xml2js": "0.4.14",
146
140
  "@types/yargs": "17.0.33",
147
- "chai": "5.2.0",
148
- "chai-as-promised": "8.0.1",
141
+ "braces": ">=3.0.3",
142
+ "chai": "5.3.3",
143
+ "chai-as-promised": "8.0.2",
149
144
  "conventional-changelog-cli": "^5.0.0",
150
145
  "grunt": "1.6.1",
151
146
  "grunt-contrib-clean": "2.0.1",
@@ -156,11 +151,11 @@
156
151
  "grunt-ts": "6.0.0-beta.22",
157
152
  "husky": "9.1.7",
158
153
  "istanbul": "0.4.5",
159
- "latest-version": "9.0.0",
160
- "lint-staged": "~15.4.3",
154
+ "lint-staged": "~15.5.2",
161
155
  "mocha": "11.1.0",
162
- "sinon": "19.0.2",
163
- "source-map-support": "0.5.21"
156
+ "sinon": "19.0.5",
157
+ "source-map-support": "0.5.21",
158
+ "xml2js": ">=0.5.0"
164
159
  },
165
160
  "optionalDependencies": {
166
161
  "fsevents": "*"
@@ -159,10 +159,10 @@ allprojects {
159
159
  }
160
160
 
161
161
 
162
- def computeCompileSdkVersion = { -> project.hasProperty("compileSdk") ? compileSdk : 34 }
163
- def computeTargetSdkVersion = { -> project.hasProperty("targetSdk") ? targetSdk : 34 as int }
162
+ def computeCompileSdkVersion = { -> project.hasProperty("compileSdk") ? compileSdk : 35 }
163
+ def computeTargetSdkVersion = { -> project.hasProperty("targetSdk") ? targetSdk : 35 as int }
164
164
  def computeBuildToolsVersion = { ->
165
- project.hasProperty("buildToolsVersion") ? buildToolsVersion : "34.0.0"
165
+ project.hasProperty("buildToolsVersion") ? buildToolsVersion : "35.0.1"
166
166
  }
167
167
 
168
168
  android {