nativescript 9.1.1-dev.1 → 9.1.2-dev.2026-09-24-36031892256

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 (74) hide show
  1. package/README.md +13 -8
  2. package/config/test-deps-versions-generated.json +1 -1
  3. package/docs/man_pages/project/testing/build-windows.md +64 -0
  4. package/docs/man_pages/project/testing/build.md +4 -2
  5. package/docs/man_pages/project/testing/debug-windows.md +69 -0
  6. package/docs/man_pages/project/testing/debug.md +5 -2
  7. package/docs/man_pages/project/testing/run-windows.md +63 -0
  8. package/docs/man_pages/project/testing/run.md +5 -2
  9. package/lib/bootstrap.js +5 -0
  10. package/lib/commands/build.d.ts +10 -0
  11. package/lib/commands/build.js +41 -1
  12. package/lib/commands/debug.d.ts +12 -0
  13. package/lib/commands/debug.js +28 -1
  14. package/lib/commands/run.d.ts +14 -0
  15. package/lib/commands/run.js +35 -1
  16. package/lib/commands/typings.d.ts +1 -0
  17. package/lib/commands/typings.js +55 -0
  18. package/lib/common/bootstrap.js +1 -0
  19. package/lib/common/commands/doctor.d.ts +7 -0
  20. package/lib/common/commands/doctor.js +18 -1
  21. package/lib/common/definitions/mobile.d.ts +9 -0
  22. package/lib/common/file-system.js +34 -6
  23. package/lib/common/http-client.js +9 -2
  24. package/lib/common/mobile/device-platforms-constants.d.ts +2 -0
  25. package/lib/common/mobile/device-platforms-constants.js +4 -0
  26. package/lib/common/mobile/mobile-core/devices-service.d.ts +2 -1
  27. package/lib/common/mobile/mobile-core/devices-service.js +7 -1
  28. package/lib/common/mobile/mobile-helper.d.ts +1 -0
  29. package/lib/common/mobile/mobile-helper.js +9 -0
  30. package/lib/common/mobile/windows/windows-application-manager.d.ts +25 -0
  31. package/lib/common/mobile/windows/windows-application-manager.js +237 -0
  32. package/lib/common/mobile/windows/windows-device-discovery.d.ts +9 -0
  33. package/lib/common/mobile/windows/windows-device-discovery.js +27 -0
  34. package/lib/common/mobile/windows/windows-device-file-system.d.ts +15 -0
  35. package/lib/common/mobile/windows/windows-device-file-system.js +74 -0
  36. package/lib/common/mobile/windows/windows-device.d.ts +13 -0
  37. package/lib/common/mobile/windows/windows-device.js +110 -0
  38. package/lib/constants.d.ts +12 -2
  39. package/lib/constants.js +15 -4
  40. package/lib/controllers/prepare-controller.js +3 -0
  41. package/lib/controllers/run-controller.js +1 -0
  42. package/lib/data/build-data.d.ts +11 -0
  43. package/lib/data/build-data.js +18 -1
  44. package/lib/data/prepare-data.d.ts +4 -0
  45. package/lib/data/prepare-data.js +8 -1
  46. package/lib/declarations.d.ts +9 -0
  47. package/lib/definitions/livesync.d.ts +3 -0
  48. package/lib/definitions/project.d.ts +10 -0
  49. package/lib/device-path-provider.d.ts +3 -1
  50. package/lib/device-path-provider.js +13 -1
  51. package/lib/options.js +19 -0
  52. package/lib/project-data.js +5 -0
  53. package/lib/resolvers/livesync-service-resolver.js +3 -0
  54. package/lib/services/apple-portal/apple-portal-session-service.d.ts +1 -0
  55. package/lib/services/apple-portal/apple-portal-session-service.js +34 -0
  56. package/lib/services/build-data-service.d.ts +2 -2
  57. package/lib/services/build-data-service.js +3 -0
  58. package/lib/services/build-info-file-service.js +1 -0
  59. package/lib/services/bundler/bundler-compiler-service.js +1 -0
  60. package/lib/services/livesync/windows-device-livesync-service.d.ts +14 -0
  61. package/lib/services/livesync/windows-device-livesync-service.js +47 -0
  62. package/lib/services/livesync/windows-livesync-service.d.ts +13 -0
  63. package/lib/services/livesync/windows-livesync-service.js +19 -0
  64. package/lib/services/platform/add-platform-service.js +9 -1
  65. package/lib/services/platforms-data-service.d.ts +1 -1
  66. package/lib/services/platforms-data-service.js +2 -1
  67. package/lib/services/prepare-data-service.d.ts +2 -2
  68. package/lib/services/prepare-data-service.js +4 -1
  69. package/lib/services/project-cleanup-service.d.ts +1 -0
  70. package/lib/services/project-cleanup-service.js +30 -1
  71. package/lib/services/project-data-service.js +18 -0
  72. package/lib/services/windows-project-service.d.ts +42 -0
  73. package/lib/services/windows-project-service.js +907 -0
  74. package/package.json +3 -3
@@ -28,6 +28,9 @@ class TypingsCommand {
28
28
  else if (this.$mobileHelper.isiOSPlatform(platform)) {
29
29
  result = await this.handleiOSTypings();
30
30
  }
31
+ else if (this.$mobileHelper.isWindowsPlatform(platform)) {
32
+ result = await this.handleWindowsTypings();
33
+ }
31
34
  let typingsFolder = "./typings";
32
35
  if (this.$options.copyTo) {
33
36
  this.$fs.copyFile(path.resolve(this.$projectData.projectDir, "typings"), this.$options.copyTo);
@@ -146,6 +149,58 @@ class TypingsCommand {
146
149
  path.resolve(this.$projectData.projectDir, "typings", "android"),
147
150
  ], "exit", { stdio: "inherit" });
148
151
  }
152
+ async handleWindowsTypings() {
153
+ if (!this.$hostInfo.isWindows) {
154
+ this.$logger.warn("Windows typings can only be generated on Windows.");
155
+ return false;
156
+ }
157
+ const outDir = path.resolve(this.$projectData.projectDir, "typings", "windows");
158
+ this.$fs.ensureDirectoryExists(outDir);
159
+ const toolsDir = path.resolve(this.$projectData.projectDir, "platforms", "windows", "tools");
160
+ const arch = process.arch === "arm64" ? "arm64" : "x64";
161
+ const resolveGenerator = () => [
162
+ path.join(toolsDir, `typings-generator-${arch}.exe`),
163
+ path.join(toolsDir, "typings-generator.exe"),
164
+ ].find((p) => this.$fs.exists(p));
165
+ let generatorPath = resolveGenerator();
166
+ if (!generatorPath) {
167
+ this.$logger.warn("No platforms folder found, preparing project now...");
168
+ await this.$childProcess.spawnFromEvent(this.$hostInfo.isWindows ? "ns.cmd" : "ns", ["prepare", "windows"], "exit", { stdio: "inherit", shell: this.$hostInfo.isWindows });
169
+ generatorPath = resolveGenerator();
170
+ }
171
+ if (!generatorPath) {
172
+ this.$logger.warn([
173
+ `Could not find the Windows typings generator under ${toolsDir}.`,
174
+ "Ensure @nativescript/windows is installed and the project has been prepared.",
175
+ ].join("\n"));
176
+ return false;
177
+ }
178
+ const asArray = (input) => {
179
+ if (!input) {
180
+ return [];
181
+ }
182
+ return typeof input === "string" ? [input] : input;
183
+ };
184
+ const generatorArgs = ["--out-dir", outDir];
185
+ if (this.$options.root) {
186
+ generatorArgs.push("--root", this.$options.root);
187
+ }
188
+ if (this.$options.roots) {
189
+ generatorArgs.push("--roots", this.$options.roots);
190
+ }
191
+ if (this.$options.input) {
192
+ generatorArgs.push("--input", this.$options.input);
193
+ }
194
+ for (const lib of asArray(this.$options.lib)) {
195
+ generatorArgs.push("--lib", lib);
196
+ }
197
+ if (this.$options.libs) {
198
+ generatorArgs.push("--libs", this.$options.libs);
199
+ }
200
+ await this.$childProcess.spawnFromEvent(generatorPath, generatorArgs, "exit", {
201
+ stdio: "inherit",
202
+ });
203
+ }
149
204
  async handleiOSTypings() {
150
205
  if (this.$options.filter !== undefined) {
151
206
  this.$logger.warn("--filter flag is not supported yet.");
@@ -45,6 +45,7 @@ yok_1.injector.require("deviceDiscovery", "./mobile/mobile-core/device-discovery
45
45
  yok_1.injector.require("iOSDeviceDiscovery", "./mobile/mobile-core/ios-device-discovery");
46
46
  yok_1.injector.require("iOSSimulatorDiscovery", "./mobile/mobile-core/ios-simulator-discovery");
47
47
  yok_1.injector.require("androidDeviceDiscovery", "./mobile/mobile-core/android-device-discovery");
48
+ yok_1.injector.require("windowsDeviceDiscovery", "./mobile/windows/windows-device-discovery");
48
49
  yok_1.injector.require("androidEmulatorDiscovery", "./mobile/mobile-core/android-emulator-discovery");
49
50
  yok_1.injector.require("iOSDevice", "./mobile/ios/device/ios-device");
50
51
  yok_1.injector.require("iOSDeviceProductNameMapper", "./mobile/ios/ios-device-product-name-mapper");
@@ -21,3 +21,10 @@ export declare class DoctorAndroidCommand implements ICommand {
21
21
  allowedParameters: ICommandParameter[];
22
22
  execute(args: string[]): Promise<void>;
23
23
  }
24
+ export declare class DoctorWindowsCommand implements ICommand {
25
+ private $doctorService;
26
+ private $projectHelper;
27
+ constructor($doctorService: IDoctorService, $projectHelper: IProjectHelper);
28
+ allowedParameters: ICommandParameter[];
29
+ execute(args: string[]): Promise<void>;
30
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DoctorAndroidCommand = exports.DoctorIosCommand = exports.DoctorCommand = void 0;
3
+ exports.DoctorWindowsCommand = exports.DoctorAndroidCommand = exports.DoctorIosCommand = exports.DoctorCommand = void 0;
4
4
  const yok_1 = require("../yok");
5
5
  const constants_1 = require("../../constants");
6
6
  class DoctorCommand {
@@ -53,3 +53,20 @@ class DoctorAndroidCommand {
53
53
  }
54
54
  exports.DoctorAndroidCommand = DoctorAndroidCommand;
55
55
  yok_1.injector.registerCommand("doctor|android", DoctorAndroidCommand);
56
+ class DoctorWindowsCommand {
57
+ constructor($doctorService, $projectHelper) {
58
+ this.$doctorService = $doctorService;
59
+ this.$projectHelper = $projectHelper;
60
+ this.allowedParameters = [];
61
+ }
62
+ execute(args) {
63
+ return this.$doctorService.printWarnings({
64
+ trackResult: false,
65
+ projectDir: this.$projectHelper.projectDir,
66
+ forceCheck: true,
67
+ platform: constants_1.PlatformTypes.windows,
68
+ });
69
+ }
70
+ }
71
+ exports.DoctorWindowsCommand = DoctorWindowsCommand;
72
+ yok_1.injector.registerCommand("doctor|windows", DoctorWindowsCommand);
@@ -367,6 +367,12 @@ declare global {
367
367
 
368
368
  interface IStartApplicationData extends IApplicationData {
369
369
  waitForDebugger?: boolean;
370
+ /**
371
+ * True when launching as part of a debug session (`ns debug`), regardless of --debug-brk.
372
+ * Windows uses this to signal the host to start the inspector (via a sentinel file);
373
+ * a plain `ns run` leaves it unset so the inspector/devtools server is never created.
374
+ */
375
+ debugMode?: boolean;
370
376
  }
371
377
 
372
378
  interface IInstallAppData extends IApplicationData {
@@ -1106,6 +1112,7 @@ declare global {
1106
1112
  isAndroidPlatform(platform: string): boolean;
1107
1113
  isiOSPlatform(platform: string): boolean;
1108
1114
  isvisionOSPlatform(platform: string): boolean;
1115
+ isWindowsPlatform(platform: string): boolean;
1109
1116
  isApplePlatform(platform: string): boolean;
1110
1117
  normalizePlatformName(platform: string): string;
1111
1118
  validatePlatformName(platform: string): string;
@@ -1150,10 +1157,12 @@ declare global {
1150
1157
  iOS: string;
1151
1158
  Android: string;
1152
1159
  visionOS: string;
1160
+ Windows: string;
1153
1161
 
1154
1162
  isiOS(value: string): boolean;
1155
1163
  isAndroid(value: string): boolean;
1156
1164
  isvisionOS(value: string): boolean;
1165
+ isWindows(value: string): boolean;
1157
1166
  }
1158
1167
 
1159
1168
  interface IDeviceApplication {
@@ -107,10 +107,16 @@ let FileSystem = FileSystem_1 = class FileSystem {
107
107
  }
108
108
  }
109
109
  deleteDirectory(directory) {
110
- shelljs.rm("-rf", directory);
111
- const err = shelljs.error();
112
- if (err !== null) {
113
- throw new Error(err);
110
+ var _a;
111
+ try {
112
+ fs.rmSync(directory, { recursive: true, force: true });
113
+ }
114
+ catch (e) {
115
+ shelljs.rm("-rf", directory);
116
+ const err = shelljs.error();
117
+ if (err !== null) {
118
+ throw new Error((_a = e === null || e === void 0 ? void 0 : e.message) !== null && _a !== void 0 ? _a : err);
119
+ }
114
120
  }
115
121
  }
116
122
  deleteDirectorySafe(directory) {
@@ -242,7 +248,10 @@ let FileSystem = FileSystem_1 = class FileSystem {
242
248
  return;
243
249
  }
244
250
  this.createDirectory((0, path_1.dirname)(destinationFileName));
245
- shelljs.cp("-rf", sourceFileName, destinationFileName);
251
+ const normalizedSource = process.platform === "win32"
252
+ ? sourceFileName.replace(/\\/g, "/")
253
+ : sourceFileName;
254
+ shelljs.cp("-rf", normalizedSource, destinationFileName);
246
255
  const err = shelljs.error();
247
256
  if (err) {
248
257
  throw new Error(err);
@@ -291,7 +300,26 @@ let FileSystem = FileSystem_1 = class FileSystem {
291
300
  }
292
301
  }
293
302
  rename(oldPath, newPath) {
294
- fs.renameSync(oldPath, newPath);
303
+ const maxAttempts = 5;
304
+ const delayMs = 200;
305
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
306
+ try {
307
+ fs.renameSync(oldPath, newPath);
308
+ return;
309
+ }
310
+ catch (e) {
311
+ if (e.code === "EPERM" && attempt < maxAttempts) {
312
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, delayMs * attempt);
313
+ continue;
314
+ }
315
+ if (e.code === "EPERM" && process.platform === "win32") {
316
+ fs.cpSync(oldPath, newPath, { recursive: true });
317
+ this.deleteDirectory(oldPath);
318
+ return;
319
+ }
320
+ throw e;
321
+ }
322
+ }
295
323
  }
296
324
  renameIfExists(oldPath, newPath) {
297
325
  try {
@@ -70,7 +70,7 @@ class HttpClient {
70
70
  },
71
71
  });
72
72
  }
73
- const result = await (0, axios_1.default)({
73
+ let httpOptions = {
74
74
  url: options.url,
75
75
  headers: options.headers,
76
76
  method: options.method,
@@ -80,7 +80,14 @@ class HttpClient {
80
80
  data: options.body,
81
81
  responseType: options.pipeTo ? "stream" : undefined,
82
82
  onDownloadProgress: options.onDownloadProgress,
83
- }).catch((err) => {
83
+ };
84
+ if (Number.isFinite(options.maxRedirects)) {
85
+ httpOptions.maxRedirects = options.maxRedirects;
86
+ }
87
+ if (options.validateStatus !== undefined) {
88
+ httpOptions.validateStatus = options.validateStatus;
89
+ }
90
+ const result = await (0, axios_1.default)(httpOptions).catch((err) => {
84
91
  this.$logger.trace("An error occurred while sending the request:", err);
85
92
  if (err.response) {
86
93
  const errorMessage = this.getErrorMessage(err.response.status, null);
@@ -2,7 +2,9 @@ export declare class DevicePlatformsConstants implements Mobile.IDevicePlatforms
2
2
  iOS: string;
3
3
  Android: string;
4
4
  visionOS: string;
5
+ Windows: string;
5
6
  isiOS(value: string): boolean;
6
7
  isAndroid(value: string): boolean;
7
8
  isvisionOS(value: string): boolean;
9
+ isWindows(value: string): boolean;
8
10
  }
@@ -7,6 +7,7 @@ class DevicePlatformsConstants {
7
7
  this.iOS = "iOS";
8
8
  this.Android = "Android";
9
9
  this.visionOS = "visionOS";
10
+ this.Windows = "Windows";
10
11
  }
11
12
  isiOS(value) {
12
13
  return value.toLowerCase() === this.iOS.toLowerCase();
@@ -17,6 +18,9 @@ class DevicePlatformsConstants {
17
18
  isvisionOS(value) {
18
19
  return value.toLowerCase() === this.visionOS.toLowerCase();
19
20
  }
21
+ isWindows(value) {
22
+ return value.toLowerCase() === this.Windows.toLowerCase();
23
+ }
20
24
  }
21
25
  exports.DevicePlatformsConstants = DevicePlatformsConstants;
22
26
  yok_1.injector.register("devicePlatformsConstants", DevicePlatformsConstants);
@@ -8,6 +8,7 @@ export declare class DevicesService extends EventEmitter implements Mobile.IDevi
8
8
  private $iOSSimulatorDiscovery;
9
9
  private $iOSDeviceDiscovery;
10
10
  private $androidDeviceDiscovery;
11
+ private $windowsDeviceDiscovery;
11
12
  private $staticConfig;
12
13
  private $messages;
13
14
  private $mobileHelper;
@@ -34,7 +35,7 @@ export declare class DevicesService extends EventEmitter implements Mobile.IDevi
34
35
  private _allDeviceDiscoveries;
35
36
  private deviceDetectionInterval;
36
37
  private emulatorDetectionInterval;
37
- constructor($logger: ILogger, $errors: IErrors, $iOSSimulatorDiscovery: Mobile.IiOSSimulatorDiscovery, $iOSDeviceDiscovery: Mobile.IDeviceDiscovery, $androidDeviceDiscovery: Mobile.IDeviceDiscovery, $staticConfig: Config.IStaticConfig, $messages: IMessages, $mobileHelper: Mobile.IMobileHelper, $deviceLogProvider: Mobile.IDeviceLogProvider, $hostInfo: IHostInfo, $injector: IInjector, $options: IOptions, $androidProcessService: Mobile.IAndroidProcessService, $iOSEmulatorServices: Mobile.IiOSSimulatorService, $androidEmulatorServices: Mobile.IEmulatorPlatformService, $androidEmulatorDiscovery: Mobile.IDeviceDiscovery, $emulatorHelper: Mobile.IEmulatorHelper, $prompter: IPrompter, $devicePlatformsConstants: Mobile.IDevicePlatformsConstants);
38
+ constructor($logger: ILogger, $errors: IErrors, $iOSSimulatorDiscovery: Mobile.IiOSSimulatorDiscovery, $iOSDeviceDiscovery: Mobile.IDeviceDiscovery, $androidDeviceDiscovery: Mobile.IDeviceDiscovery, $windowsDeviceDiscovery: Mobile.IDeviceDiscovery, $staticConfig: Config.IStaticConfig, $messages: IMessages, $mobileHelper: Mobile.IMobileHelper, $deviceLogProvider: Mobile.IDeviceLogProvider, $hostInfo: IHostInfo, $injector: IInjector, $options: IOptions, $androidProcessService: Mobile.IAndroidProcessService, $iOSEmulatorServices: Mobile.IiOSSimulatorService, $androidEmulatorServices: Mobile.IEmulatorPlatformService, $androidEmulatorDiscovery: Mobile.IDeviceDiscovery, $emulatorHelper: Mobile.IEmulatorHelper, $prompter: IPrompter, $devicePlatformsConstants: Mobile.IDevicePlatformsConstants);
38
39
  pickSingleDevice(options: Mobile.IPickSingleDeviceOptions): Promise<Mobile.IDevice>;
39
40
  getEmulatorImages(options?: Mobile.IListEmulatorsOptions): Promise<Mobile.IListEmulatorsOutput>;
40
41
  startEmulator(options: Mobile.IStartEmulatorOptions): Promise<string[]>;
@@ -20,13 +20,14 @@ const helpers = require("../../helpers");
20
20
  const helpers_1 = require("../../helpers");
21
21
  const yok_1 = require("../../yok");
22
22
  class DevicesService extends events_1.EventEmitter {
23
- constructor($logger, $errors, $iOSSimulatorDiscovery, $iOSDeviceDiscovery, $androidDeviceDiscovery, $staticConfig, $messages, $mobileHelper, $deviceLogProvider, $hostInfo, $injector, $options, $androidProcessService, $iOSEmulatorServices, $androidEmulatorServices, $androidEmulatorDiscovery, $emulatorHelper, $prompter, $devicePlatformsConstants) {
23
+ constructor($logger, $errors, $iOSSimulatorDiscovery, $iOSDeviceDiscovery, $androidDeviceDiscovery, $windowsDeviceDiscovery, $staticConfig, $messages, $mobileHelper, $deviceLogProvider, $hostInfo, $injector, $options, $androidProcessService, $iOSEmulatorServices, $androidEmulatorServices, $androidEmulatorDiscovery, $emulatorHelper, $prompter, $devicePlatformsConstants) {
24
24
  super();
25
25
  this.$logger = $logger;
26
26
  this.$errors = $errors;
27
27
  this.$iOSSimulatorDiscovery = $iOSSimulatorDiscovery;
28
28
  this.$iOSDeviceDiscovery = $iOSDeviceDiscovery;
29
29
  this.$androidDeviceDiscovery = $androidDeviceDiscovery;
30
+ this.$windowsDeviceDiscovery = $windowsDeviceDiscovery;
30
31
  this.$staticConfig = $staticConfig;
31
32
  this.$messages = $messages;
32
33
  this.$mobileHelper = $mobileHelper;
@@ -52,6 +53,7 @@ class DevicesService extends events_1.EventEmitter {
52
53
  this.$iOSDeviceDiscovery,
53
54
  this.$androidDeviceDiscovery,
54
55
  this.$iOSSimulatorDiscovery,
56
+ this.$windowsDeviceDiscovery,
55
57
  ];
56
58
  }
57
59
  async pickSingleDevice(options) {
@@ -206,6 +208,7 @@ class DevicesService extends events_1.EventEmitter {
206
208
  this.$iOSSimulatorDiscovery,
207
209
  this.$iOSDeviceDiscovery,
208
210
  this.$androidDeviceDiscovery,
211
+ this.$windowsDeviceDiscovery,
209
212
  ].forEach(this.attachToDeviceDiscoveryEvents.bind(this));
210
213
  }
211
214
  attachToKnownEmulatorDiscoveryEvents() {
@@ -703,6 +706,9 @@ class DevicesService extends events_1.EventEmitter {
703
706
  this.$hostInfo.isDarwin) {
704
707
  await this.$iOSSimulatorDiscovery.startLookingForDevices(deviceLookingOptions);
705
708
  }
709
+ else if (this.$mobileHelper.isWindowsPlatform(platform)) {
710
+ await this.$windowsDeviceDiscovery.startLookingForDevices(deviceLookingOptions);
711
+ }
706
712
  }
707
713
  async executeCore(action, canExecute) {
708
714
  if (this._device) {
@@ -12,6 +12,7 @@ export declare class MobileHelper implements Mobile.IMobileHelper {
12
12
  isAndroidPlatform(platform: string): boolean;
13
13
  isiOSPlatform(platform: string): boolean;
14
14
  isvisionOSPlatform(platform: string): boolean;
15
+ isWindowsPlatform(platform: string): boolean;
15
16
  isApplePlatform(platform: string): boolean;
16
17
  normalizePlatformName(platform: string): string;
17
18
  validatePlatformName(platform: string): string;
@@ -17,6 +17,7 @@ class MobileHelper {
17
17
  this.$devicePlatformsConstants.iOS,
18
18
  this.$devicePlatformsConstants.Android,
19
19
  this.$devicePlatformsConstants.visionOS,
20
+ this.$devicePlatformsConstants.Windows,
20
21
  ];
21
22
  }
22
23
  isAndroidPlatform(platform) {
@@ -34,6 +35,11 @@ class MobileHelper {
34
35
  this.$devicePlatformsConstants.visionOS.toLowerCase() ===
35
36
  platform.toLowerCase());
36
37
  }
38
+ isWindowsPlatform(platform) {
39
+ return !!(platform &&
40
+ this.$devicePlatformsConstants.Windows.toLowerCase() ===
41
+ platform.toLowerCase());
42
+ }
37
43
  isApplePlatform(platform) {
38
44
  return this.isiOSPlatform(platform) || this.isvisionOSPlatform(platform);
39
45
  }
@@ -47,6 +53,9 @@ class MobileHelper {
47
53
  else if (this.isvisionOSPlatform(platform)) {
48
54
  return "visionOS";
49
55
  }
56
+ else if (this.isWindowsPlatform(platform)) {
57
+ return "Windows";
58
+ }
50
59
  return undefined;
51
60
  }
52
61
  validatePlatformName(platform) {
@@ -0,0 +1,25 @@
1
+ import { ApplicationManagerBase } from "../application-manager-base";
2
+ import { IHooksService, IChildProcess, IDictionary } from "../../declarations";
3
+ import { IBuildData } from "../../../definitions/build";
4
+ export declare class WindowsApplicationManager extends ApplicationManagerBase {
5
+ private $childProcess;
6
+ private _restartLogStream?;
7
+ private _runningPid;
8
+ private _packageFamilyNames;
9
+ private _installedExePaths;
10
+ constructor($logger: ILogger, $hooksService: IHooksService, $deviceLogProvider: Mobile.IDeviceLogProvider, $childProcess: IChildProcess, _restartLogStream?: () => Promise<void>);
11
+ getInstalledApplications(): Promise<string[]>;
12
+ isApplicationInstalled(appIdentifier: string): Promise<boolean>;
13
+ installApplication(packageFilePath: string, appIdentifier?: string, _buildData?: IBuildData): Promise<void>;
14
+ uninstallApplication(appIdentifier: string): Promise<void>;
15
+ restartApplication(appData: Mobile.IStartApplicationData): Promise<void>;
16
+ getLogFilePath(): string;
17
+ getCrashLogPath(): string | null;
18
+ startApplication(appData: Mobile.IStartApplicationData): Promise<void>;
19
+ stopApplication(appData: Mobile.IApplicationData): Promise<void>;
20
+ tryStartApplication(appData: Mobile.IApplicationData): Promise<void>;
21
+ getDebuggableApps(): Promise<Mobile.IDeviceApplicationInformation[]>;
22
+ getDebuggableAppViews(_appIdentifiers: string[]): Promise<IDictionary<Mobile.IDebugWebViewInfo[]>>;
23
+ private _resolvePackageFamilyName;
24
+ private _writeMarker;
25
+ }
@@ -0,0 +1,237 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WindowsApplicationManager = void 0;
4
+ const fs = require("fs");
5
+ const os = require("os");
6
+ const path = require("path");
7
+ const child_process_1 = require("child_process");
8
+ const application_manager_base_1 = require("../application-manager-base");
9
+ class WindowsApplicationManager extends application_manager_base_1.ApplicationManagerBase {
10
+ constructor($logger, $hooksService, $deviceLogProvider, $childProcess, _restartLogStream) {
11
+ super($logger, $hooksService, $deviceLogProvider);
12
+ this.$childProcess = $childProcess;
13
+ this._restartLogStream = _restartLogStream;
14
+ this._runningPid = null;
15
+ this._packageFamilyNames = new Map();
16
+ this._installedExePaths = {};
17
+ }
18
+ async getInstalledApplications() {
19
+ try {
20
+ const result = await this.$childProcess.spawnFromEvent("powershell.exe", [
21
+ "-NoProfile",
22
+ "-Command",
23
+ "Get-AppxPackage | Select-Object -ExpandProperty PackageFamilyName",
24
+ ], "close", {}, { throwError: false });
25
+ return (result.stdout || "")
26
+ .split(/\r?\n/)
27
+ .map((s) => s.trim())
28
+ .filter(Boolean);
29
+ }
30
+ catch (_a) {
31
+ return [];
32
+ }
33
+ }
34
+ async isApplicationInstalled(appIdentifier) {
35
+ if (appIdentifier &&
36
+ Object.prototype.hasOwnProperty.call(this._installedExePaths, appIdentifier)) {
37
+ return true;
38
+ }
39
+ return super.isApplicationInstalled(appIdentifier);
40
+ }
41
+ async installApplication(packageFilePath, appIdentifier, _buildData) {
42
+ if (packageFilePath === null || packageFilePath === void 0 ? void 0 : packageFilePath.toLowerCase().endsWith(".exe")) {
43
+ this.$logger.info(`[Windows] Registering EXE: ${packageFilePath}`);
44
+ const exeBase = path.basename(packageFilePath, path.extname(packageFilePath));
45
+ if (appIdentifier) {
46
+ this._installedExePaths[appIdentifier] = packageFilePath;
47
+ }
48
+ this._installedExePaths[exeBase] = packageFilePath;
49
+ return;
50
+ }
51
+ this.$logger.info(`[Windows] Installing MSIX/APPX from: ${packageFilePath}`);
52
+ if (appIdentifier) {
53
+ try {
54
+ this.$logger.info(`[Windows] Attempting to remove existing package: ${appIdentifier}`);
55
+ await this.uninstallApplication(appIdentifier);
56
+ }
57
+ catch (err) {
58
+ this.$logger.warn(`[Windows] Pre-install uninstall failed: ${err}`);
59
+ }
60
+ }
61
+ const isLooseManifest = packageFilePath.toLowerCase().endsWith("appxmanifest.xml");
62
+ let addAppxCommand;
63
+ if (isLooseManifest) {
64
+ addAppxCommand = `Add-AppxPackage -ForceApplicationShutdown -Register -Path "${packageFilePath}"`;
65
+ }
66
+ else {
67
+ const arch = process.arch === "arm64" ? "arm64" : "x64";
68
+ const dependencyDir = path.join(path.dirname(packageFilePath), "Dependencies", arch);
69
+ const dependencyGlob = path.join(dependencyDir, "*.msix");
70
+ addAppxCommand = fs.existsSync(dependencyDir)
71
+ ? `$deps = Get-ChildItem -Path "${dependencyGlob}" -ErrorAction SilentlyContinue; ` +
72
+ `if ($deps) { Add-AppxPackage -Path "${packageFilePath}" -DependencyPath $deps.FullName -ForceApplicationShutdown } ` +
73
+ `else { Add-AppxPackage -Path "${packageFilePath}" -ForceApplicationShutdown }`
74
+ : `Add-AppxPackage -Path "${packageFilePath}" -ForceApplicationShutdown`;
75
+ }
76
+ await this.$childProcess.spawnFromEvent("powershell.exe", [
77
+ "-NoProfile",
78
+ "-ExecutionPolicy",
79
+ "Bypass",
80
+ "-Command",
81
+ addAppxCommand,
82
+ ], "close", {}, { throwError: true });
83
+ if (appIdentifier) {
84
+ await this._resolvePackageFamilyName(appIdentifier);
85
+ }
86
+ }
87
+ async uninstallApplication(appIdentifier) {
88
+ delete this._installedExePaths[appIdentifier];
89
+ this._packageFamilyNames.delete(appIdentifier);
90
+ await this.$childProcess.spawnFromEvent("powershell.exe", [
91
+ "-NoProfile",
92
+ "-Command",
93
+ `Get-AppxPackage -Name "${appIdentifier}" | Remove-AppxPackage`,
94
+ ], "close", {}, { throwError: false });
95
+ }
96
+ async restartApplication(appData) {
97
+ await this.stopApplication(appData);
98
+ await this.startApplication(appData);
99
+ }
100
+ getLogFilePath() {
101
+ if (this._packageFamilyNames.size > 0) {
102
+ const pfn = this._packageFamilyNames.values().next().value;
103
+ const localAppData = process.env.LOCALAPPDATA;
104
+ if (localAppData && pfn) {
105
+ return path.join(localAppData, "Packages", pfn, "LocalState", "console.log");
106
+ }
107
+ }
108
+ const systemConsoleLog = path.join(os.tmpdir(), "console.log");
109
+ const systemLegacyLog = path.join(os.tmpdir(), "ns_trace.log");
110
+ if (fs.existsSync(systemConsoleLog))
111
+ return systemConsoleLog;
112
+ if (fs.existsSync(systemLegacyLog))
113
+ return systemLegacyLog;
114
+ return systemConsoleLog;
115
+ }
116
+ getCrashLogPath() {
117
+ if (this._packageFamilyNames.size > 0) {
118
+ const pfn = this._packageFamilyNames.values().next().value;
119
+ const localAppData = process.env.LOCALAPPDATA;
120
+ if (localAppData && pfn) {
121
+ return path.join(localAppData, "Packages", pfn, "LocalState", "nativescript-crash.log");
122
+ }
123
+ }
124
+ return null;
125
+ }
126
+ async startApplication(appData) {
127
+ var _a, _b;
128
+ const exeCandidate = (appData.appId && this._installedExePaths[appData.appId]) ||
129
+ (appData.projectName && this._installedExePaths[appData.projectName]);
130
+ const isExe = !!(exeCandidate && fs.existsSync(exeCandidate));
131
+ if (!isExe) {
132
+ await this._resolvePackageFamilyName(appData.appId);
133
+ }
134
+ try {
135
+ fs.writeFileSync(this.getLogFilePath(), "", "utf8");
136
+ }
137
+ catch (_c) { }
138
+ if (isExe) {
139
+ if (appData.waitForDebugger) {
140
+ this.$logger.info(`[Windows] --debug-brk is not supported for EXE targets.`);
141
+ }
142
+ this.$logger.info(`[Windows] Launching EXE: ${exeCandidate}`);
143
+ const proc = (0, child_process_1.spawn)(exeCandidate, [], { detached: true, stdio: "ignore" });
144
+ proc.unref();
145
+ this._runningPid = (_a = proc.pid) !== null && _a !== void 0 ? _a : null;
146
+ proc.on("exit", () => {
147
+ if (this._runningPid === proc.pid) {
148
+ this._runningPid = null;
149
+ }
150
+ });
151
+ }
152
+ else {
153
+ const pfn = (_b = this._packageFamilyNames.get(appData.appId)) !== null && _b !== void 0 ? _b : appData.appId;
154
+ if (appData.debugMode) {
155
+ this._writeMarker(pfn, "ns-inspector");
156
+ }
157
+ if (appData.waitForDebugger) {
158
+ this._writeMarker(pfn, "ns-debugbreak");
159
+ }
160
+ const appId = "App";
161
+ this.$logger.info(`[Windows] Launching UWP: ${pfn}!${appId}`);
162
+ const proc = (0, child_process_1.spawn)("explorer.exe", [`shell:AppsFolder\\${pfn}!${appId}`], {
163
+ detached: true,
164
+ stdio: "ignore",
165
+ });
166
+ proc.unref();
167
+ }
168
+ if (this._restartLogStream) {
169
+ await this._restartLogStream();
170
+ }
171
+ }
172
+ async stopApplication(appData) {
173
+ if (this._runningPid) {
174
+ try {
175
+ process.kill(this._runningPid);
176
+ }
177
+ catch (_a) {
178
+ }
179
+ this._runningPid = null;
180
+ }
181
+ else {
182
+ await this.$childProcess.spawnFromEvent("powershell.exe", [
183
+ "-NoProfile",
184
+ "-Command",
185
+ `Stop-Process -Name "${appData.projectName}" -ErrorAction SilentlyContinue`,
186
+ ], "close", {}, { throwError: false });
187
+ }
188
+ }
189
+ async tryStartApplication(appData) {
190
+ try {
191
+ await this.startApplication(appData);
192
+ }
193
+ catch (_a) {
194
+ }
195
+ }
196
+ async getDebuggableApps() {
197
+ return [];
198
+ }
199
+ async getDebuggableAppViews(_appIdentifiers) {
200
+ return {};
201
+ }
202
+ async _resolvePackageFamilyName(appId) {
203
+ var _a;
204
+ const cached = this._packageFamilyNames.get(appId);
205
+ if (cached)
206
+ return cached;
207
+ try {
208
+ const result = await this.$childProcess.spawnFromEvent("powershell.exe", [
209
+ "-NoProfile",
210
+ "-Command",
211
+ `(Get-AppxPackage | Where-Object { $_.Name -eq "${appId}" -or $_.PackageFullName -like "*${appId}*" } | Select-Object -First 1).PackageFamilyName`,
212
+ ], "close", {}, { throwError: false });
213
+ const pfn = (result.stdout || "").trim();
214
+ if (pfn) {
215
+ this._packageFamilyNames.set(appId, pfn);
216
+ }
217
+ }
218
+ catch (_b) {
219
+ }
220
+ return (_a = this._packageFamilyNames.get(appId)) !== null && _a !== void 0 ? _a : appId;
221
+ }
222
+ _writeMarker(pfn, name) {
223
+ const localAppData = process.env.LOCALAPPDATA;
224
+ if (!localAppData)
225
+ return;
226
+ const markerPath = path.join(localAppData, "Packages", pfn, "LocalState", name);
227
+ try {
228
+ fs.mkdirSync(path.dirname(markerPath), { recursive: true });
229
+ fs.writeFileSync(markerPath, "", "utf8");
230
+ this.$logger.info(`[Windows] Wrote ${name} marker: ${markerPath}`);
231
+ }
232
+ catch (e) {
233
+ this.$logger.warn(`[Windows] Could not write ${name} marker: ${e}`);
234
+ }
235
+ }
236
+ }
237
+ exports.WindowsApplicationManager = WindowsApplicationManager;
@@ -0,0 +1,9 @@
1
+ import { DeviceDiscovery } from "../mobile-core/device-discovery";
2
+ import { IInjector } from "../../definitions/yok";
3
+ export declare class WindowsDeviceDiscovery extends DeviceDiscovery implements Mobile.IDeviceDiscovery {
4
+ private $injector;
5
+ private $mobileHelper;
6
+ private _deviceAdded;
7
+ constructor($injector: IInjector, $mobileHelper: Mobile.IMobileHelper);
8
+ startLookingForDevices(options?: Mobile.IDeviceLookingOptions): Promise<void>;
9
+ }