nativescript 9.0.0-alpha.9 → 9.0.0-dev.0

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.
Files changed (89) hide show
  1. package/config/config.json +1 -1
  2. package/config/test-deps-versions-generated.json +3 -3
  3. package/docs/build-jekyll-md.sh +1 -1
  4. package/docs/man_pages/config/config-get.md +36 -0
  5. package/docs/man_pages/config/config-set.md +40 -0
  6. package/docs/man_pages/config/config.md +39 -0
  7. package/docs/man_pages/project/hooks/hooks.md +35 -0
  8. package/docs/man_pages/start.md +1 -0
  9. package/lib/.d.ts +4 -0
  10. package/lib/bootstrap.js +2 -0
  11. package/lib/commands/build.js +22 -3
  12. package/lib/commands/clean.js +3 -2
  13. package/lib/commands/config.js +9 -3
  14. package/lib/commands/hooks/common.js +79 -0
  15. package/lib/commands/hooks/hooks-lock.js +100 -0
  16. package/lib/commands/hooks/hooks.js +71 -0
  17. package/lib/commands/plugin/build-plugin.js +6 -2
  18. package/lib/commands/typings.js +1 -1
  19. package/lib/common/declarations.d.ts +5 -0
  20. package/lib/common/definitions/extensibility.d.ts +2 -2
  21. package/lib/common/definitions/mobile.d.ts +78 -72
  22. package/lib/common/file-system.js +1 -1
  23. package/lib/common/logger/logger.js +1 -1
  24. package/lib/common/mobile/android/android-device.js +8 -2
  25. package/lib/common/mobile/mobile-core/devices-service.js +1 -1
  26. package/lib/common/plist-parser.js +3 -3
  27. package/lib/common/project-helper.js +15 -2
  28. package/lib/common/services/hooks-service.js +1 -1
  29. package/lib/config.js +2 -38
  30. package/lib/constants.js +3 -2
  31. package/lib/controllers/build-controller.js +1 -1
  32. package/lib/controllers/deploy-controller.js +5 -2
  33. package/lib/controllers/migrate-controller.js +6 -5
  34. package/lib/controllers/platform-controller.js +3 -1
  35. package/lib/controllers/prepare-controller.js +54 -13
  36. package/lib/controllers/run-controller.js +12 -13
  37. package/lib/controllers/update-controller.js +2 -2
  38. package/lib/data/build-data.js +2 -0
  39. package/lib/declarations.d.ts +3 -1
  40. package/lib/definitions/android-plugin-migrator.d.ts +3 -2
  41. package/lib/definitions/build.d.ts +4 -2
  42. package/lib/definitions/hooks.d.ts +1 -0
  43. package/lib/definitions/ios-debugger-port-service.d.ts +1 -1
  44. package/lib/definitions/livesync.d.ts +1 -1
  45. package/lib/definitions/project.d.ts +14 -0
  46. package/lib/definitions/run.d.ts +2 -4
  47. package/lib/helpers/deploy-command-helper.js +1 -0
  48. package/lib/nativescript-cli.js +28 -0
  49. package/lib/options.js +9 -2
  50. package/lib/project-data.js +8 -2
  51. package/lib/services/analytics/analytics-broker-process.js +1 -1
  52. package/lib/services/analytics/analytics-service.js +1 -1
  53. package/lib/services/android/gradle-build-args-service.js +21 -7
  54. package/lib/services/android/gradle-build-service.js +15 -1
  55. package/lib/services/android-plugin-build-service.js +58 -44
  56. package/lib/services/android-project-service.js +63 -4
  57. package/lib/services/build-artifacts-service.js +24 -9
  58. package/lib/services/bundler/bundler-compiler-service.js +77 -104
  59. package/lib/services/cocoapods-service.js +10 -4
  60. package/lib/services/device/device-install-app-service.js +27 -5
  61. package/lib/services/extensibility-service.js +1 -1
  62. package/lib/services/ios/xcodebuild-args-service.js +7 -5
  63. package/lib/services/ios-project-service.js +5 -2
  64. package/lib/services/plugins-service.js +3 -2
  65. package/lib/services/project-data-service.js +16 -18
  66. package/lib/services/timeline-profiler-service.js +21 -13
  67. package/lib/services/versions-service.js +2 -1
  68. package/package.json +16 -13
  69. package/vendor/aab-tool/README.txt +1 -1
  70. package/vendor/aab-tool/bundletool.jar +0 -0
  71. package/vendor/gradle-app/app/build.gradle +1292 -0
  72. package/vendor/gradle-app/app/gradle-helpers/AnalyticsCollector.gradle +48 -0
  73. package/vendor/gradle-app/app/gradle-helpers/BuildToolTask.gradle +50 -0
  74. package/vendor/gradle-app/app/gradle-helpers/CustomExecutionLogger.gradle +52 -0
  75. package/vendor/gradle-app/app/gradle.properties +45 -0
  76. package/vendor/gradle-app/build.gradle +170 -0
  77. package/vendor/gradle-app/settings.gradle +78 -0
  78. package/vendor/gradle-plugin/build.gradle +214 -91
  79. package/vendor/gradle-plugin/gradle.properties +2 -18
  80. package/vendor/gradle-plugin/settings.gradle +23 -11
  81. package/lib/common/resources/platform-tools/android/darwin/NOTICE.txt +0 -3407
  82. package/lib/common/resources/platform-tools/android/darwin/adb +0 -0
  83. package/lib/common/resources/platform-tools/android/linux/NOTICE.txt +0 -4451
  84. package/lib/common/resources/platform-tools/android/linux/adb +0 -0
  85. package/lib/common/resources/platform-tools/android/win32/AdbWinApi.dll +0 -0
  86. package/lib/common/resources/platform-tools/android/win32/AdbWinUsbApi.dll +0 -0
  87. package/lib/common/resources/platform-tools/android/win32/NOTICE.txt +0 -4451
  88. package/lib/common/resources/platform-tools/android/win32/adb.exe +0 -0
  89. package/lib/common/resources/platform-tools/android/win32/fastboot.exe +0 -0
@@ -4,5 +4,5 @@
4
4
  "ANDROID_DEBUG_UI_MAC": "Google Chrome",
5
5
  "USE_POD_SANDBOX": false,
6
6
  "DISABLE_HOOKS": false,
7
- "GA_TRACKING_ID": "UA-111455-44"
7
+ "GA_TRACKING_ID": "UA-111455-51"
8
8
  }
@@ -3,14 +3,14 @@
3
3
  "karma": "6.4.4",
4
4
  "karma-coverage": "2.2.1",
5
5
  "karma-nativescript-launcher": "1.0.0",
6
- "mocha": "11.7.2",
6
+ "mocha": "11.7.5",
7
7
  "karma-mocha": "2.0.1",
8
8
  "karma-chai": "0.1.0",
9
9
  "karma-jasmine": "4.0.2",
10
10
  "karma-qunit": "4.2.1",
11
- "@types/karma-chai": "0.1.7",
11
+ "@types/karma-chai": "0.1.8",
12
12
  "@types/mocha": "10.0.10",
13
- "@types/jasmine": "5.1.9",
13
+ "@types/jasmine": "5.1.12",
14
14
  "@types/qunit": "2.19.13",
15
15
  "nyc": "17.1.0"
16
16
  }
@@ -4,4 +4,4 @@ set -e
4
4
  rm -rf docs-cli
5
5
  npm install --ignore-scripts
6
6
 
7
- grunt docs-jekyll
7
+ npx grunt docs-jekyll
@@ -0,0 +1,36 @@
1
+ <% if (isJekyll) { %>---
2
+ title: ns config get
3
+ position: 2
4
+ ---<% } %>
5
+
6
+ # ns config get
7
+
8
+ ### Description
9
+
10
+ Prints the value for a specific key from the project's NativeScript configuration.
11
+
12
+ ### Commands
13
+
14
+ Usage | Synopsis
15
+ ------|-------
16
+ General | `$ ns config get <key>`
17
+
18
+ ### Arguments
19
+
20
+ * `<key>` — The configuration key in dot-notation. Examples: `ios.id`, `android.codeCache`, `bundler`.
21
+
22
+ ### Examples
23
+
24
+ * `$ ns config get ios.id`
25
+ * `$ ns config get android.codeCache`
26
+ * `$ ns config get bundler`
27
+
28
+ <% if(isHtml) { %>
29
+
30
+ ### Related Commands
31
+
32
+ Command | Description
33
+ ----------|----------
34
+ [config](config.html) | Lists all configuration values for the current project.
35
+ [config set](config-set.html) | Sets the value for the specified configuration key.
36
+ <% } %>
@@ -0,0 +1,40 @@
1
+ <% if (isJekyll) { %>---
2
+ title: ns config set
3
+ position: 3
4
+ ---<% } %>
5
+
6
+ # ns config set
7
+
8
+ ### Description
9
+
10
+ Sets the value for a specific key in the project's NativeScript configuration.
11
+
12
+ ### Commands
13
+
14
+ Usage | Synopsis
15
+ ------|-------
16
+ General | `$ ns config set <key> <value>`
17
+
18
+ ### Arguments
19
+
20
+ * `<key>` — The configuration key in dot-notation. Examples: `ios.id`, `android.codeCache`, `bundler`.
21
+ * `<value>` — The value to set. Parsed as JSON when possible (e.g. `true`, `42`, `{ "foo": "bar" }`). Otherwise treated as a string.
22
+
23
+ ### Examples
24
+
25
+ * `$ ns config set ios.id org.nativescript.myapp`
26
+ * `$ ns config set android.codeCache true`
27
+ * `$ ns config set bundler vite`
28
+
29
+ ### Notes
30
+
31
+ * Setting whole objects is not supported. Update individual keys instead. For example, use:
32
+ `$ ns config set android.codeCache true`
33
+
34
+ ### Related Commands
35
+
36
+ Command | Description
37
+ ----------|----------
38
+ [config](config.html) | Lists all configuration values for the current project.
39
+ [config get](config-get.html) | Prints the value for the specified configuration key.
40
+ <% } %>
@@ -0,0 +1,39 @@
1
+ <% if (isJekyll) { %>---
2
+ title: ns config
3
+ position: 1
4
+ ---<% } %>
5
+
6
+ # ns config
7
+
8
+ ### Description
9
+
10
+ View and manage your project's NativeScript configuration stored in `nativescript.config.(js|ts)` (or legacy `nsconfig.json`).
11
+
12
+ ### Commands
13
+
14
+ Usage | Synopsis
15
+ ------|---------
16
+ List all config | `$ ns config`
17
+ Get a value | `$ ns config get <key>`
18
+ Set a value | `$ ns config set <key> <value>`
19
+
20
+ ### Examples
21
+
22
+ * `$ ns config` — prints all configuration values.
23
+ * `$ ns config get ios.id` — prints the iOS bundle identifier.
24
+ * `$ ns config set android.codeCache true` — enables Android V8 code cache.
25
+
26
+ ### Notes
27
+
28
+ * Keys use dot-notation, for example: `ios.id`, `android.codeCache`, `bundler`.
29
+ * Values are parsed as JSON when possible. Use quotes for strings with spaces.
30
+
31
+ <% if(isHtml) { %>
32
+
33
+ ### Related Commands
34
+
35
+ Command | Description
36
+ ----------|----------
37
+ [config get](config-get.html) | Prints the value for the specified configuration key.
38
+ [config set](config-set.html) | Sets the value for the specified configuration key.
39
+ <% } %>
@@ -0,0 +1,35 @@
1
+ <% if (isJekyll) { %>---
2
+ title: ns hooks
3
+ position: 1
4
+ ---<% } %>
5
+
6
+ # ns create
7
+
8
+ ### Description
9
+
10
+ Manages lifecycle hooks from installed plugins.
11
+
12
+ ### Commands
13
+
14
+ Usage | Synopsis
15
+ ---------|---------
16
+ Install | `$ ns hooks install`
17
+ List | `$ ns hooks list`
18
+ Lock | `$ ns hooks lock`
19
+ Verify | `$ ns hooks verify`
20
+
21
+ #### Install
22
+
23
+ Installs hooks from each installed plugin dependency.
24
+
25
+ #### List
26
+
27
+ Lists the plugins which have hooks and which scripts they install
28
+
29
+ #### Lock
30
+
31
+ Generates a `hooks-lock.json` containing the hooks that are in the current versions of the plugins.
32
+
33
+ #### Verify
34
+
35
+ Verifies that the hooks contained in the installed plugins match those listed in the `hooks-lock.json` file.
@@ -51,6 +51,7 @@ Command | Description
51
51
  [plugin](lib-management/plugin.html) | Lets you manage the plugins for your project.
52
52
  [open](project/configuration/open.md) | Opens the native project in Xcode/Android Studio.
53
53
  [widget ios](project/configuration/widget.md) | Adds a new iOS widget to the project.
54
+ [hooks](project/hooks/hooks.html) | Installs lifecycle hooks from plugins.
54
55
  ## Publishing Commands
55
56
  Command | Description
56
57
  ---|---
package/lib/.d.ts CHANGED
@@ -23,6 +23,9 @@
23
23
  /// <reference path="commands/generate-assets.ts" />
24
24
  /// <reference path="commands/generate-help.ts" />
25
25
  /// <reference path="commands/generate.ts" />
26
+ /// <reference path="commands/hooks/common.ts" />
27
+ /// <reference path="commands/hooks/hooks-lock.ts" />
28
+ /// <reference path="commands/hooks/hooks.ts" />
26
29
  /// <reference path="commands/info.ts" />
27
30
  /// <reference path="commands/install.ts" />
28
31
  /// <reference path="commands/list-platforms.ts" />
@@ -257,6 +260,7 @@
257
260
  /// <reference path="definitions/files-hash-service.d.ts" />
258
261
  /// <reference path="definitions/gradle.d.ts" />
259
262
  /// <reference path="definitions/hmr-status-service.d.ts" />
263
+ /// <reference path="definitions/hooks.d.ts" />
260
264
  /// <reference path="definitions/initialize-service.d.ts" />
261
265
  /// <reference path="definitions/ios-debugger-port-service.d.ts" />
262
266
  /// <reference path="definitions/ios.d.ts" />
package/lib/bootstrap.js CHANGED
@@ -128,6 +128,8 @@ yok_1.injector.requireCommand("plugin|remove", "./commands/plugin/remove-plugin"
128
128
  yok_1.injector.requireCommand("plugin|update", "./commands/plugin/update-plugin");
129
129
  yok_1.injector.requireCommand("plugin|build", "./commands/plugin/build-plugin");
130
130
  yok_1.injector.requireCommand("plugin|create", "./commands/plugin/create-plugin");
131
+ yok_1.injector.requireCommand(["hooks|*list", "hooks|install"], "./commands/hooks/hooks");
132
+ yok_1.injector.requireCommand(["hooks|lock", "hooks|verify"], "./commands/hooks/hooks-lock");
131
133
  yok_1.injector.require("doctorService", "./services/doctor-service");
132
134
  yok_1.injector.require("xcprojService", "./services/xcproj-service");
133
135
  yok_1.injector.require("versionsService", "./services/versions-service");
@@ -25,7 +25,10 @@ class BuildCommandBase extends command_base_1.ValidatePlatformCommandBase {
25
25
  }
26
26
  async executeCore(args) {
27
27
  const platform = args[0].toLowerCase();
28
- const buildData = this.$buildDataService.getBuildData(this.$projectData.projectDir, platform, this.$options);
28
+ const buildData = this.$buildDataService.getBuildData(this.$projectData.projectDir, platform, {
29
+ ...this.$options.argv,
30
+ buildFilterDevicesArch: false,
31
+ });
29
32
  const outputPath = await this.$buildController.prepareAndBuild(buildData);
30
33
  return outputPath;
31
34
  }
@@ -119,9 +122,25 @@ class BuildVisionOsCommand extends BuildIosCommand {
119
122
  this.$options = $options;
120
123
  this.$migrateController = $migrateController;
121
124
  }
125
+ async execute(args) {
126
+ await this.executeCore([
127
+ this.$devicePlatformsConstants.visionOS.toLowerCase(),
128
+ ]);
129
+ }
122
130
  async canExecute(args) {
123
- this.$errors.fail('Building for "visionOS" platform is not supported via the CLI. Please open the project in Xcode and build it from there.');
124
- return false;
131
+ const platform = this.$devicePlatformsConstants.visionOS;
132
+ if (!this.$options.force) {
133
+ await this.$migrateController.validate({
134
+ projectDir: this.$projectData.projectDir,
135
+ platforms: [platform],
136
+ });
137
+ }
138
+ super.validatePlatform(platform);
139
+ let canExecute = await super.canExecuteCommandBase(platform);
140
+ if (canExecute) {
141
+ canExecute = await super.validateArgs(args, platform);
142
+ }
143
+ return canExecute;
125
144
  }
126
145
  }
127
146
  exports.BuildVisionOsCommand = BuildVisionOsCommand;
@@ -42,9 +42,10 @@ function promiseMap(values, mapper, concurrency = 10) {
42
42
  });
43
43
  }
44
44
  class CleanCommand {
45
- constructor($projectCleanupService, $projectConfigService, $terminalSpinnerService, $projectService, $prompter, $logger, $options, $childProcess, $staticConfig) {
45
+ constructor($projectCleanupService, $projectConfigService, $projectData, $terminalSpinnerService, $projectService, $prompter, $logger, $options, $childProcess, $staticConfig) {
46
46
  this.$projectCleanupService = $projectCleanupService;
47
47
  this.$projectConfigService = $projectConfigService;
48
+ this.$projectData = $projectData;
48
49
  this.$terminalSpinnerService = $terminalSpinnerService;
49
50
  this.$projectService = $projectService;
50
51
  this.$prompter = $prompter;
@@ -67,7 +68,7 @@ class CleanCommand {
67
68
  spinner.start("Cleaning project...\n");
68
69
  let pathsToClean = [
69
70
  constants.HOOKS_DIR_NAME,
70
- constants.PLATFORMS_DIR_NAME,
71
+ this.$projectData.getBuildRelativeDirectoryPath(),
71
72
  constants.NODE_MODULES_FOLDER_NAME,
72
73
  ];
73
74
  try {
@@ -4,15 +4,21 @@ exports.ConfigSetCommand = exports.ConfigGetCommand = exports.ConfigListCommand
4
4
  const yok_1 = require("../common/yok");
5
5
  const color_1 = require("../color");
6
6
  class ConfigListCommand {
7
- constructor($projectConfigService, $logger) {
7
+ constructor($projectConfigService, $options, $logger) {
8
8
  this.$projectConfigService = $projectConfigService;
9
+ this.$options = $options;
9
10
  this.$logger = $logger;
10
11
  this.allowedParameters = [];
11
12
  }
12
13
  async execute(args) {
13
14
  try {
14
15
  const config = this.$projectConfigService.readConfig();
15
- this.$logger.info(this.getValueString(config));
16
+ if (this.$options.json) {
17
+ console.log(JSON.stringify(config));
18
+ }
19
+ else {
20
+ this.$logger.info(this.getValueString(config));
21
+ }
16
22
  }
17
23
  catch (error) {
18
24
  this.$logger.info("Failed to read config. Error is: ", error);
@@ -75,7 +81,7 @@ class ConfigSetCommand {
75
81
  const convertedValue = this.getConvertedValue(value);
76
82
  const existingKey = current !== undefined;
77
83
  const keyDisplay = color_1.color.green(key);
78
- const currentDisplay = color_1.color.yellow(current);
84
+ const currentDisplay = current ? color_1.color.yellow(current) : "";
79
85
  const updatedDisplay = color_1.color.cyan(convertedValue);
80
86
  this.$logger.info(`${existingKey ? "Updating" : "Setting"} ${keyDisplay}${existingKey ? ` from ${currentDisplay} ` : " "}to ${updatedDisplay}`);
81
87
  try {
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HooksVerify = exports.LOCK_FILE_NAME = void 0;
4
+ const path = require("path");
5
+ const crypto = require("crypto");
6
+ exports.LOCK_FILE_NAME = "nativescript-lock.json";
7
+ class HooksVerify {
8
+ constructor($projectData, $errors, $fs, $logger) {
9
+ this.$projectData = $projectData;
10
+ this.$errors = $errors;
11
+ this.$fs = $fs;
12
+ this.$logger = $logger;
13
+ this.allowedParameters = [];
14
+ this.$projectData.initializeProjectData();
15
+ }
16
+ async verifyHooksLock(plugins, hooksLockPath) {
17
+ var _a;
18
+ let lockFileContent;
19
+ let hooksLock;
20
+ try {
21
+ lockFileContent = this.$fs.readText(hooksLockPath, "utf8");
22
+ hooksLock = JSON.parse(lockFileContent);
23
+ }
24
+ catch (err) {
25
+ this.$errors.fail(`❌ Failed to read or parse ${exports.LOCK_FILE_NAME} at ${hooksLockPath}`);
26
+ }
27
+ const lockMap = new Map();
28
+ for (const plugin of hooksLock) {
29
+ const hookMap = new Map();
30
+ for (const hook of plugin.hooks) {
31
+ hookMap.set(hook.type, hook.hash);
32
+ }
33
+ lockMap.set(plugin.name, hookMap);
34
+ }
35
+ let isValid = true;
36
+ for (const plugin of plugins) {
37
+ const pluginLockHooks = lockMap.get(plugin.name);
38
+ if (!pluginLockHooks) {
39
+ this.$logger.error(`❌ Plugin '${plugin.name}' not found in ${exports.LOCK_FILE_NAME}`);
40
+ isValid = false;
41
+ continue;
42
+ }
43
+ for (const hook of ((_a = plugin.nativescript) === null || _a === void 0 ? void 0 : _a.hooks) || []) {
44
+ const expectedHash = pluginLockHooks.get(hook.type);
45
+ if (!expectedHash) {
46
+ this.$logger.error(`❌ Missing hook '${hook.type}' for plugin '${plugin.name}' in ${exports.LOCK_FILE_NAME}`);
47
+ isValid = false;
48
+ continue;
49
+ }
50
+ let fileContent;
51
+ try {
52
+ fileContent = this.$fs.readFile(path.join(plugin.fullPath, hook.script));
53
+ }
54
+ catch (err) {
55
+ this.$logger.error(`❌ Cannot read script file '${hook.script}' for hook '${hook.type}' in plugin '${plugin.name}'`);
56
+ isValid = false;
57
+ continue;
58
+ }
59
+ const actualHash = crypto
60
+ .createHash("sha256")
61
+ .update(fileContent)
62
+ .digest("hex");
63
+ if (actualHash !== expectedHash) {
64
+ this.$logger.error(`❌ Hash mismatch for '${hook.script}' (${hook.type} in ${plugin.name}):`);
65
+ this.$logger.error(` Expected: ${expectedHash}`);
66
+ this.$logger.error(` Actual: ${actualHash}`);
67
+ isValid = false;
68
+ }
69
+ }
70
+ }
71
+ if (isValid) {
72
+ this.$logger.info("✅ All hooks verified successfully. No issues found.");
73
+ }
74
+ else {
75
+ this.$errors.fail("❌ One or more hooks failed verification.");
76
+ }
77
+ }
78
+ }
79
+ exports.HooksVerify = HooksVerify;
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HooksVerifyPluginCommand = exports.HooksLockPluginCommand = void 0;
4
+ const yok_1 = require("../../common/yok");
5
+ const path = require("path");
6
+ const crypto = require("crypto");
7
+ const common_1 = require("./common");
8
+ class HooksLockPluginCommand {
9
+ constructor($pluginsService, $projectData, $errors, $fs, $logger) {
10
+ this.$pluginsService = $pluginsService;
11
+ this.$projectData = $projectData;
12
+ this.$errors = $errors;
13
+ this.$fs = $fs;
14
+ this.$logger = $logger;
15
+ this.allowedParameters = [];
16
+ this.$projectData.initializeProjectData();
17
+ }
18
+ async execute() {
19
+ var _a, _b;
20
+ const plugins = await this.$pluginsService.getAllInstalledPlugins(this.$projectData);
21
+ if (plugins && plugins.length > 0) {
22
+ const pluginsWithHooks = [];
23
+ for (const plugin of plugins) {
24
+ if (((_b = (_a = plugin.nativescript) === null || _a === void 0 ? void 0 : _a.hooks) === null || _b === void 0 ? void 0 : _b.length) > 0) {
25
+ pluginsWithHooks.push(plugin);
26
+ }
27
+ }
28
+ await this.writeHooksLockFile(pluginsWithHooks, this.$projectData.projectDir);
29
+ }
30
+ else {
31
+ this.$logger.info("No plugins with hooks found.");
32
+ }
33
+ }
34
+ async canExecute(args) {
35
+ return true;
36
+ }
37
+ async writeHooksLockFile(plugins, outputDir) {
38
+ var _a;
39
+ const output = [];
40
+ for (const plugin of plugins) {
41
+ const hooks = [];
42
+ for (const hook of ((_a = plugin.nativescript) === null || _a === void 0 ? void 0 : _a.hooks) || []) {
43
+ try {
44
+ const fileContent = this.$fs.readFile(path.join(plugin.fullPath, hook.script));
45
+ const hash = crypto
46
+ .createHash("sha256")
47
+ .update(fileContent)
48
+ .digest("hex");
49
+ hooks.push({
50
+ type: hook.type,
51
+ hash,
52
+ });
53
+ }
54
+ catch (err) {
55
+ this.$logger.warn(`Warning: Failed to read script '${hook.script}' for plugin '${plugin.name}'. Skipping this hook.`);
56
+ continue;
57
+ }
58
+ }
59
+ output.push({ name: plugin.name, hooks });
60
+ }
61
+ const filePath = path.resolve(outputDir, common_1.LOCK_FILE_NAME);
62
+ try {
63
+ this.$fs.writeFile(filePath, JSON.stringify(output, null, 2), "utf8");
64
+ this.$logger.info(`✅ ${common_1.LOCK_FILE_NAME} written to: ${filePath}`);
65
+ }
66
+ catch (err) {
67
+ this.$errors.fail(`❌ Failed to write ${common_1.LOCK_FILE_NAME}: ${err}`);
68
+ }
69
+ }
70
+ }
71
+ exports.HooksLockPluginCommand = HooksLockPluginCommand;
72
+ class HooksVerifyPluginCommand extends common_1.HooksVerify {
73
+ constructor($pluginsService, $projectData, $errors, $fs, $logger) {
74
+ super($projectData, $errors, $fs, $logger);
75
+ this.$pluginsService = $pluginsService;
76
+ this.allowedParameters = [];
77
+ }
78
+ async execute() {
79
+ var _a, _b;
80
+ const plugins = await this.$pluginsService.getAllInstalledPlugins(this.$projectData);
81
+ if (plugins && plugins.length > 0) {
82
+ const pluginsWithHooks = [];
83
+ for (const plugin of plugins) {
84
+ if (((_b = (_a = plugin.nativescript) === null || _a === void 0 ? void 0 : _a.hooks) === null || _b === void 0 ? void 0 : _b.length) > 0) {
85
+ pluginsWithHooks.push(plugin);
86
+ }
87
+ }
88
+ await this.verifyHooksLock(pluginsWithHooks, path.join(this.$projectData.projectDir, common_1.LOCK_FILE_NAME));
89
+ }
90
+ else {
91
+ this.$logger.info("No plugins with hooks found.");
92
+ }
93
+ }
94
+ async canExecute(args) {
95
+ return true;
96
+ }
97
+ }
98
+ exports.HooksVerifyPluginCommand = HooksVerifyPluginCommand;
99
+ yok_1.injector.registerCommand(["hooks|lock"], HooksLockPluginCommand);
100
+ yok_1.injector.registerCommand(["hooks|verify"], HooksVerifyPluginCommand);
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HooksListPluginCommand = exports.HooksPluginCommand = void 0;
4
+ const yok_1 = require("../../common/yok");
5
+ const path = require("path");
6
+ const constants_1 = require("../../constants");
7
+ const helpers_1 = require("../../common/helpers");
8
+ const nsHooks = require("@nativescript/hook");
9
+ const common_1 = require("./common");
10
+ class HooksPluginCommand extends common_1.HooksVerify {
11
+ constructor($pluginsService, $projectData, $errors, $fs, $logger) {
12
+ super($projectData, $errors, $fs, $logger);
13
+ this.$pluginsService = $pluginsService;
14
+ this.allowedParameters = [];
15
+ }
16
+ async execute(args) {
17
+ var _a, _b;
18
+ const isList = args.length > 0 && args[0] === "list" ? true : false;
19
+ const plugins = await this.$pluginsService.getAllInstalledPlugins(this.$projectData);
20
+ if (plugins && plugins.length > 0) {
21
+ const hooksDir = path.join(this.$projectData.projectDir, constants_1.HOOKS_DIR_NAME);
22
+ const pluginsWithHooks = [];
23
+ for (const plugin of plugins) {
24
+ if (((_b = (_a = plugin.nativescript) === null || _a === void 0 ? void 0 : _a.hooks) === null || _b === void 0 ? void 0 : _b.length) > 0) {
25
+ pluginsWithHooks.push(plugin);
26
+ }
27
+ }
28
+ if (isList) {
29
+ const headers = ["Plugin", "HookName", "HookPath"];
30
+ const hookDataData = pluginsWithHooks.flatMap((plugin) => plugin.nativescript.hooks.map((hook) => {
31
+ return [plugin.name, hook.type, hook.script];
32
+ }));
33
+ const hookDataTable = (0, helpers_1.createTable)(headers, hookDataData);
34
+ this.$logger.info("Hooks:");
35
+ this.$logger.info(hookDataTable.toString());
36
+ }
37
+ else {
38
+ if (this.$fs.exists(path.join(this.$projectData.projectDir, common_1.LOCK_FILE_NAME))) {
39
+ await this.verifyHooksLock(pluginsWithHooks, path.join(this.$projectData.projectDir, common_1.LOCK_FILE_NAME));
40
+ }
41
+ if (pluginsWithHooks.length === 0) {
42
+ if (!this.$fs.exists(hooksDir)) {
43
+ this.$fs.createDirectory(hooksDir);
44
+ }
45
+ }
46
+ for (const plugin of pluginsWithHooks) {
47
+ nsHooks(plugin.fullPath).postinstall();
48
+ }
49
+ }
50
+ }
51
+ }
52
+ async canExecute(args) {
53
+ if (args.length > 0 && args[0] !== "list") {
54
+ this.$errors.failWithHelp(`Invalid argument ${args[0]}. Supported argument is "list".`);
55
+ }
56
+ return true;
57
+ }
58
+ }
59
+ exports.HooksPluginCommand = HooksPluginCommand;
60
+ class HooksListPluginCommand extends HooksPluginCommand {
61
+ constructor($pluginsService, $projectData, $errors, $fs, $logger) {
62
+ super($pluginsService, $projectData, $errors, $fs, $logger);
63
+ this.allowedParameters = [];
64
+ }
65
+ async execute() {
66
+ await super.execute(["list"]);
67
+ }
68
+ }
69
+ exports.HooksListPluginCommand = HooksListPluginCommand;
70
+ yok_1.injector.registerCommand(["hooks|install"], HooksPluginCommand);
71
+ yok_1.injector.registerCommand(["hooks|*list"], HooksListPluginCommand);
@@ -6,13 +6,14 @@ const path = require("path");
6
6
  const constants = require("../../constants");
7
7
  const yok_1 = require("../../common/yok");
8
8
  class BuildPluginCommand {
9
- constructor($androidPluginBuildService, $errors, $logger, $fs, $options, $tempService) {
9
+ constructor($androidPluginBuildService, $errors, $logger, $fs, $options, $tempService, $projectData) {
10
10
  this.$androidPluginBuildService = $androidPluginBuildService;
11
11
  this.$errors = $errors;
12
12
  this.$logger = $logger;
13
13
  this.$fs = $fs;
14
14
  this.$options = $options;
15
15
  this.$tempService = $tempService;
16
+ this.$projectData = $projectData;
16
17
  this.allowedParameters = [];
17
18
  this.pluginProjectPath = path.resolve(this.$options.path || ".");
18
19
  }
@@ -27,13 +28,16 @@ class BuildPluginCommand {
27
28
  }
28
29
  }
29
30
  const tempAndroidProject = await this.$tempService.mkdirSync("android-project");
31
+ const gradleArgs = (this.$projectData.nsConfig.android.gradleArgs || []).concat(this.$options.gradleArgs || []);
32
+ const pluginOptions = (this.$projectData.nsConfig.android.plugins || {})[pluginName] || {};
30
33
  const options = {
31
34
  gradlePath: this.$options.gradlePath,
32
- gradleArgs: this.$options.gradleArgs,
35
+ gradleArgs,
33
36
  aarOutputDir: platformsAndroidPath,
34
37
  platformsAndroidDirPath: platformsAndroidPath,
35
38
  pluginName: pluginName,
36
39
  tempPluginDirPath: tempAndroidProject,
40
+ ...pluginOptions
37
41
  };
38
42
  const androidPluginBuildResult = await this.$androidPluginBuildService.buildAar(options);
39
43
  if (androidPluginBuildResult) {
@@ -118,7 +118,7 @@ class TypingsCommand {
118
118
  return false;
119
119
  }
120
120
  this.$fs.ensureDirectoryExists(path.resolve(this.$projectData.projectDir, "typings", "android"));
121
- const dtsGeneratorPath = path.resolve(this.$projectData.projectDir, "platforms", "android", "build-tools", "dts-generator.jar");
121
+ const dtsGeneratorPath = path.resolve(this.$projectData.projectDir, this.$projectData.getBuildRelativeDirectoryPath(), "android", "build-tools", "dts-generator.jar");
122
122
  if (!this.$fs.exists(dtsGeneratorPath)) {
123
123
  this.$logger.warn("No platforms folder found, preparing project now...");
124
124
  await this.$childProcess.spawnFromEvent(this.$hostInfo.isWindows ? "ns.cmd" : "ns", ["prepare", "android"], "exit", { stdio: "inherit", shell: this.$hostInfo.isWindows });
@@ -1276,6 +1276,11 @@ interface IDashedOption {
1276
1276
  * Specifies either a single option key (string), or an array of options that must be followed by option values.
1277
1277
  */
1278
1278
  requiresArg?: any;
1279
+
1280
+ /**
1281
+ * Set to true to define the option as an array option https://github.com/yargs/yargs/blob/main/docs/api.md#array
1282
+ */
1283
+ array?: any;
1279
1284
  }
1280
1285
 
1281
1286
  /**
@@ -124,7 +124,7 @@ interface IExtensibilityService {
124
124
  * Gives the name of the extension that contains a required command.
125
125
  * The method finds all extensions from npm and checks the command property defined in the nativescript key of the package.json.
126
126
  * Based on specified input array, the method tries to find a suitable command that is defined in the extension.
127
- * @example In case the input is `tns execute this command now`, the array will be ["execute", "this", "command", "now"].
127
+ * @example In case the input is `ns execute this command now`, the array will be ["execute", "this", "command", "now"].
128
128
  * There may be an extension that defines execute|this as a command. The method will check each extension for the following commands:
129
129
  * execute|this|command|now, execute|this|command, execute|this, execute
130
130
  * In case it finds any of this commands, the method will return the extension name and the command name.
@@ -132,7 +132,7 @@ interface IExtensibilityService {
132
132
  * @returns {IExtensionCommandInfo} Information about the extension and the registered command.
133
133
  */
134
134
  getExtensionNameWhereCommandIsRegistered(
135
- inputOpts: IGetExtensionCommandInfoParams
135
+ inputOpts: IGetExtensionCommandInfoParams,
136
136
  ): Promise<IExtensionCommandInfo>;
137
137
 
138
138
  /**