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.
- package/README.md +13 -8
- package/config/test-deps-versions-generated.json +1 -1
- package/docs/man_pages/project/testing/build-windows.md +64 -0
- package/docs/man_pages/project/testing/build.md +4 -2
- package/docs/man_pages/project/testing/debug-windows.md +69 -0
- package/docs/man_pages/project/testing/debug.md +5 -2
- package/docs/man_pages/project/testing/run-windows.md +63 -0
- package/docs/man_pages/project/testing/run.md +5 -2
- package/lib/bootstrap.js +5 -0
- package/lib/commands/build.d.ts +10 -0
- package/lib/commands/build.js +41 -1
- package/lib/commands/debug.d.ts +12 -0
- package/lib/commands/debug.js +28 -1
- package/lib/commands/run.d.ts +14 -0
- package/lib/commands/run.js +35 -1
- package/lib/commands/typings.d.ts +1 -0
- package/lib/commands/typings.js +55 -0
- package/lib/common/bootstrap.js +1 -0
- package/lib/common/commands/doctor.d.ts +7 -0
- package/lib/common/commands/doctor.js +18 -1
- package/lib/common/definitions/mobile.d.ts +9 -0
- package/lib/common/file-system.js +34 -6
- package/lib/common/http-client.js +9 -2
- package/lib/common/mobile/device-platforms-constants.d.ts +2 -0
- package/lib/common/mobile/device-platforms-constants.js +4 -0
- package/lib/common/mobile/mobile-core/devices-service.d.ts +2 -1
- package/lib/common/mobile/mobile-core/devices-service.js +7 -1
- package/lib/common/mobile/mobile-helper.d.ts +1 -0
- package/lib/common/mobile/mobile-helper.js +9 -0
- package/lib/common/mobile/windows/windows-application-manager.d.ts +25 -0
- package/lib/common/mobile/windows/windows-application-manager.js +237 -0
- package/lib/common/mobile/windows/windows-device-discovery.d.ts +9 -0
- package/lib/common/mobile/windows/windows-device-discovery.js +27 -0
- package/lib/common/mobile/windows/windows-device-file-system.d.ts +15 -0
- package/lib/common/mobile/windows/windows-device-file-system.js +74 -0
- package/lib/common/mobile/windows/windows-device.d.ts +13 -0
- package/lib/common/mobile/windows/windows-device.js +110 -0
- package/lib/constants.d.ts +12 -2
- package/lib/constants.js +15 -4
- package/lib/controllers/prepare-controller.js +3 -0
- package/lib/controllers/run-controller.js +1 -0
- package/lib/data/build-data.d.ts +11 -0
- package/lib/data/build-data.js +18 -1
- package/lib/data/prepare-data.d.ts +4 -0
- package/lib/data/prepare-data.js +8 -1
- package/lib/declarations.d.ts +9 -0
- package/lib/definitions/livesync.d.ts +3 -0
- package/lib/definitions/project.d.ts +10 -0
- package/lib/device-path-provider.d.ts +3 -1
- package/lib/device-path-provider.js +13 -1
- package/lib/options.js +19 -0
- package/lib/project-data.js +5 -0
- package/lib/resolvers/livesync-service-resolver.js +3 -0
- package/lib/services/apple-portal/apple-portal-session-service.d.ts +1 -0
- package/lib/services/apple-portal/apple-portal-session-service.js +34 -0
- package/lib/services/build-data-service.d.ts +2 -2
- package/lib/services/build-data-service.js +3 -0
- package/lib/services/build-info-file-service.js +1 -0
- package/lib/services/bundler/bundler-compiler-service.js +1 -0
- package/lib/services/livesync/windows-device-livesync-service.d.ts +14 -0
- package/lib/services/livesync/windows-device-livesync-service.js +47 -0
- package/lib/services/livesync/windows-livesync-service.d.ts +13 -0
- package/lib/services/livesync/windows-livesync-service.js +19 -0
- package/lib/services/platform/add-platform-service.js +9 -1
- package/lib/services/platforms-data-service.d.ts +1 -1
- package/lib/services/platforms-data-service.js +2 -1
- package/lib/services/prepare-data-service.d.ts +2 -2
- package/lib/services/prepare-data-service.js +4 -1
- package/lib/services/project-cleanup-service.d.ts +1 -0
- package/lib/services/project-cleanup-service.js +30 -1
- package/lib/services/project-data-service.js +18 -0
- package/lib/services/windows-project-service.d.ts +42 -0
- package/lib/services/windows-project-service.js +907 -0
- package/package.json +3 -3
package/lib/commands/typings.js
CHANGED
|
@@ -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.");
|
package/lib/common/bootstrap.js
CHANGED
|
@@ -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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
}
|
|
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
|
+
}
|