@akylas/nativescript-cli 8.9.4 → 8.10.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 (66) hide show
  1. package/config/test-deps-versions-generated.json +10 -10
  2. package/docs/build-jekyll-md.sh +1 -1
  3. package/docs/man_pages/config/config-get.md +36 -0
  4. package/docs/man_pages/config/config-set.md +40 -0
  5. package/docs/man_pages/config/config.md +39 -0
  6. package/docs/man_pages/project/hooks/hooks.md +35 -0
  7. package/docs/man_pages/start.md +1 -0
  8. package/lib/.d.ts +8 -3
  9. package/lib/bootstrap.js +3 -1
  10. package/lib/color.js +38 -7
  11. package/lib/commands/build.js +18 -2
  12. package/lib/commands/clean.js +1 -2
  13. package/lib/commands/config.js +1 -1
  14. package/lib/commands/embedding/embed.js +1 -1
  15. package/lib/commands/hooks/common.js +79 -0
  16. package/lib/commands/hooks/hooks-lock.js +100 -0
  17. package/lib/commands/hooks/hooks.js +71 -0
  18. package/lib/commands/post-install.js +2 -2
  19. package/lib/commands/typings.js +29 -18
  20. package/lib/common/definitions/extensibility.d.ts +2 -2
  21. package/lib/common/definitions/mobile.d.ts +72 -72
  22. package/lib/common/header.js +3 -3
  23. package/lib/common/logger/layouts/cli-layout.js +1 -1
  24. package/lib/common/logger/logger.js +3 -3
  25. package/lib/common/mobile/android/android-device.js +1 -1
  26. package/lib/common/mobile/android/android-emulator-services.js +8 -6
  27. package/lib/common/mobile/device-log-provider.js +3 -4
  28. package/lib/common/project-helper.js +15 -2
  29. package/lib/common/verify-node-version.js +1 -1
  30. package/lib/constants.js +7 -4
  31. package/lib/controllers/migrate-controller.js +3 -4
  32. package/lib/controllers/prepare-controller.js +9 -9
  33. package/lib/controllers/run-controller.js +1 -1
  34. package/lib/declarations.d.ts +5 -0
  35. package/lib/definitions/hooks.d.ts +1 -0
  36. package/lib/definitions/nativescript-dev-xcode.d.ts +25 -1
  37. package/lib/definitions/project.d.ts +52 -1
  38. package/lib/definitions/temp-service.d.ts +6 -2
  39. package/lib/helpers/key-command-helper.js +2 -1
  40. package/lib/nativescript-cli.js +28 -0
  41. package/lib/options.js +4 -0
  42. package/lib/project-data.js +10 -4
  43. package/lib/services/analytics/analytics-broker-process.js +1 -1
  44. package/lib/services/analytics-settings-service.js +2 -1
  45. package/lib/services/android/gradle-build-args-service.js +7 -3
  46. package/lib/services/android/gradle-build-service.js +4 -1
  47. package/lib/services/android-project-service.js +12 -10
  48. package/lib/services/{webpack/webpack-compiler-service.js → bundler/bundler-compiler-service.js} +254 -85
  49. package/lib/services/bundler/bundler.js +2 -0
  50. package/lib/services/extensibility-service.js +1 -1
  51. package/lib/services/ios/spm-service.js +13 -2
  52. package/lib/services/ios/xcodebuild-args-service.js +7 -5
  53. package/lib/services/ios-project-service.js +0 -1
  54. package/lib/services/ios-watch-app-service.js +540 -16
  55. package/lib/services/livesync/android-livesync-tool.js +3 -1
  56. package/lib/services/plugins-service.js +1 -0
  57. package/lib/services/project-changes-service.js +1 -1
  58. package/lib/services/temp-service.js +16 -4
  59. package/lib/services/versions-service.js +2 -1
  60. package/package.json +35 -36
  61. package/vendor/aab-tool/README.txt +1 -1
  62. package/vendor/aab-tool/bundletool.jar +0 -0
  63. package/vendor/gradle-app/app/build.gradle +20 -13
  64. package/vendor/gradle-app/app/gradle.properties +45 -0
  65. package/vendor/gradle-plugin/build.gradle +7 -6
  66. package/lib/services/webpack/webpack.d.ts +0 -227
@@ -27,7 +27,7 @@ class XcodebuildArgsService {
27
27
  let destination = "generic/platform=iOS Simulator";
28
28
  let isvisionOS = this.$devicePlatformsConstants.isvisionOS(buildConfig.platform);
29
29
  if (isvisionOS) {
30
- destination = "platform=visionOS Simulator";
30
+ destination = "generic/platform=visionOS Simulator";
31
31
  if (buildConfig._device) {
32
32
  destination += `,id=${buildConfig._device.deviceInfo.identifier}`;
33
33
  }
@@ -40,7 +40,9 @@ class XcodebuildArgsService {
40
40
  "-configuration",
41
41
  buildConfig.release ? constants_1.Configurations.Release : constants_1.Configurations.Debug,
42
42
  ])
43
- .concat(this.getBuildCommonArgs(platformData, projectData, isvisionOS ? ios_project_service_1.VisionSimulatorPlatformSdkName : ios_project_service_1.SimulatorPlatformSdkName))
43
+ .concat(this.getBuildCommonArgs(platformData, projectData, isvisionOS
44
+ ? ios_project_service_1.VisionSimulatorPlatformSdkName
45
+ : ios_project_service_1.SimulatorPlatformSdkName))
44
46
  .concat(this.getBuildLoggingArgs())
45
47
  .concat(this.getXcodeProjectArgs(platformData, projectData));
46
48
  return args;
@@ -51,7 +53,7 @@ class XcodebuildArgsService {
51
53
  let destination = "generic/platform=iOS";
52
54
  let isvisionOS = this.$devicePlatformsConstants.isvisionOS(buildConfig.platform);
53
55
  if (isvisionOS) {
54
- destination = "platform=visionOS";
56
+ destination = "generic/platform=visionOS";
55
57
  if (buildConfig._device) {
56
58
  destination += `,id=${buildConfig._device.deviceInfo.identifier}`;
57
59
  }
@@ -68,14 +70,14 @@ class XcodebuildArgsService {
68
70
  ]
69
71
  .concat(this.getXcodeProjectArgs(platformData, projectData))
70
72
  .concat(architectures)
71
- .concat(this.getBuildCommonArgs(platformData, projectData, ios_project_service_1.DevicePlatformSdkName))
73
+ .concat(this.getBuildCommonArgs(platformData, projectData, isvisionOS ? ios_project_service_1.VisionDevicePlatformSdkName : ios_project_service_1.DevicePlatformSdkName))
72
74
  .concat(this.getBuildLoggingArgs());
73
75
  return args;
74
76
  }
75
77
  async getArchitecturesArgs(buildConfig) {
76
78
  const args = [];
77
79
  if (this.$devicePlatformsConstants.isvisionOS(buildConfig.platform)) {
78
- args.push("ONLY_ACTIVE_ARCH=YES");
80
+ args.push("ONLY_ACTIVE_ARCH=YES", "EXCLUDED_ARCHS=x86_64");
79
81
  return args;
80
82
  }
81
83
  const devicesArchitectures = buildConfig.buildForDevice
@@ -371,7 +371,6 @@ class IOSProjectService extends projectServiceBaseLib.PlatformProjectServiceBase
371
371
  }
372
372
  }
373
373
  }
374
- this.$iOSWatchAppService.removeWatchApp({ pbxProjPath });
375
374
  const addedWatchApp = await this.$iOSWatchAppService.addWatchAppFromPath({
376
375
  watchAppFolderPath: path.join(resourcesDirectoryPath, platformData.normalizedPlatformName),
377
376
  projectData,
@@ -4,34 +4,154 @@ exports.IOSWatchAppService = void 0;
4
4
  const path = require("path");
5
5
  const constants_1 = require("../constants");
6
6
  const yok_1 = require("../common/yok");
7
+ const trapezedev_project_1 = require("@nstudio/trapezedev-project");
8
+ const minimatch_1 = require("minimatch");
9
+ const sourceExtensions = [
10
+ '.swift', '.m', '.mm', '.c', '.cpp', '.cc', '.cxx', '.h', '.hpp'
11
+ ];
12
+ const resourceExtensions = [
13
+ '.png', '.jpg', '.jpeg', '.gif', '.svg', '.pdf',
14
+ '.ttf', '.otf', '.woff', '.woff2',
15
+ '.xcassets',
16
+ '.storyboard', '.xib',
17
+ '.strings', '.stringsdict',
18
+ '.json', '.xml', '.plist',
19
+ '.m4a', '.mp3', '.wav', '.caf',
20
+ '.mp4', '.mov',
21
+ '.bundle',
22
+ ];
23
+ const WATCH_APP_IDENTIFIER = "watchkitapp";
24
+ const WACTCH_EXTENSION_IDENTIFIER = "watchkitextension";
25
+ const CONFIG_FILE_WATCHAPP = "watchapp.json";
26
+ const CONFIG_FILE_EXTENSION = "extension.json";
27
+ const RESOURCES_TO_IGNORE = [CONFIG_FILE_WATCHAPP, CONFIG_FILE_EXTENSION, 'node_modules'];
7
28
  class IOSWatchAppService {
8
- constructor($fs, $pbxprojDomXcode, $xcode, $iOSNativeTargetService) {
29
+ constructor($fs, $pbxprojDomXcode, $xcode, $iOSNativeTargetService, $logger) {
9
30
  this.$fs = $fs;
10
31
  this.$pbxprojDomXcode = $pbxprojDomXcode;
11
32
  this.$xcode = $xcode;
12
33
  this.$iOSNativeTargetService = $iOSNativeTargetService;
34
+ this.$logger = $logger;
35
+ }
36
+ addResourceFile(project, path, opt, group = 'WatchResources') {
37
+ const file = project.addResourceFile(path, opt, group);
38
+ project.addToResourcesPbxGroup(file, group);
39
+ }
40
+ addSourceFile(project, path, opt, group = 'WatchSrc') {
41
+ const file = project.addSourceFile(path, opt, group);
42
+ project.addToResourcesPbxGroup(file, group);
13
43
  }
14
44
  async addWatchAppFromPath({ watchAppFolderPath, projectData, platformData, pbxProjPath, }) {
45
+ var _a, _b;
15
46
  const targetUuids = [];
47
+ const targetNames = [];
16
48
  const appPath = path.join(watchAppFolderPath, constants_1.IOS_WATCHAPP_FOLDER);
17
- const extensionPath = path.join(watchAppFolderPath, constants_1.IOS_WATCHAPP_EXTENSION_FOLDER);
18
- if (!this.$fs.exists(appPath) || !this.$fs.exists(extensionPath)) {
49
+ if (!this.$fs.exists(appPath)) {
19
50
  return false;
20
51
  }
21
52
  const appFolder = this.$iOSNativeTargetService.getTargetDirectories(appPath)[0];
22
- const extensionFolder = this.$iOSNativeTargetService.getTargetDirectories(extensionPath)[0];
23
53
  const project = new this.$xcode.project(pbxProjPath);
24
54
  project.parseSync();
25
- const watchApptarget = this.$iOSNativeTargetService.addTargetToProject(appPath, appFolder, constants_1.IOSNativeTargetTypes.watchApp, project, platformData, project.getFirstTarget().uuid);
26
- this.configureTarget(appFolder, path.join(appPath, appFolder), `${projectData.projectIdentifiers.ios}.${IOSWatchAppService.WATCH_APP_IDENTIFIER}`, "watchapp.json", watchApptarget, project);
55
+ const configPath = path.join(path.join(appPath, appFolder), "watchapp.json");
56
+ const config = this.$fs.exists(configPath) ? this.$fs.readJson(configPath) : null;
57
+ const targetType = (_a = config === null || config === void 0 ? void 0 : config.targetType) !== null && _a !== void 0 ? _a : constants_1.IOSNativeTargetTypes.watchApp;
58
+ project.removeTargetsByProductType(constants_1.IOSNativeTargetProductTypes.watchApp);
59
+ project.removeTargetsByProductType(targetType);
60
+ const parentTargetUuid = project.getFirstTarget().uuid;
61
+ const watchApptarget = this.addTarget(appPath, appFolder, targetType, project, platformData, parentTargetUuid, constants_1.IOSNativeTargetTypes.watchApp);
62
+ await this.configureTarget(appFolder, path.join(appPath, appFolder), `${projectData.projectIdentifiers.ios}.${WATCH_APP_IDENTIFIER}`, configPath, config, watchApptarget, project, projectData, platformData, pbxProjPath);
27
63
  targetUuids.push(watchApptarget.uuid);
28
- const watchExtensionTarget = this.$iOSNativeTargetService.addTargetToProject(extensionPath, extensionFolder, constants_1.IOSNativeTargetTypes.watchExtension, project, platformData, watchApptarget.uuid);
29
- this.configureTarget(extensionFolder, path.join(extensionPath, extensionFolder), `${projectData.projectIdentifiers.ios}.${IOSWatchAppService.WATCH_APP_IDENTIFIER}.${IOSWatchAppService.WACTCH_EXTENSION_IDENTIFIER}`, "extension.json", watchExtensionTarget, project);
30
- targetUuids.push(watchExtensionTarget.uuid);
64
+ targetNames.push(appFolder);
65
+ const extensionPath = path.join(watchAppFolderPath, constants_1.IOS_WATCHAPP_EXTENSION_FOLDER);
66
+ if (this.$fs.exists(extensionPath)) {
67
+ const extensionFolder = this.$iOSNativeTargetService.getTargetDirectories(extensionPath)[0];
68
+ const configPath = path.join(path.join(extensionPath, extensionFolder), "extension.json");
69
+ const config = this.$fs.exists(configPath) ? this.$fs.readJson(configPath) : null;
70
+ const targetType = (_b = config === null || config === void 0 ? void 0 : config.targetType) !== null && _b !== void 0 ? _b : constants_1.IOSNativeTargetTypes.watchExtension;
71
+ project.removeTargetsByProductType(constants_1.IOSNativeTargetProductTypes.watchExtension);
72
+ project.removeTargetsByProductType(targetType);
73
+ const watchExtensionTarget = this.addTarget(extensionPath, extensionFolder, targetType, project, platformData, watchApptarget.uuid);
74
+ await this.configureTarget(extensionFolder, path.join(extensionPath, extensionFolder), `${projectData.projectIdentifiers.ios}.${WATCH_APP_IDENTIFIER}.${WACTCH_EXTENSION_IDENTIFIER}`, configPath, config, watchExtensionTarget, project, projectData, platformData, pbxProjPath);
75
+ targetUuids.push(watchExtensionTarget.uuid);
76
+ targetNames.push(extensionFolder);
77
+ }
78
+ else {
79
+ this.$logger.debug("No watch extension found - using single target mode (Xcode 14+)");
80
+ }
31
81
  this.$fs.writeFile(pbxProjPath, project.writeSync({ omitEmptyValues: true }));
82
+ const watchSPMPackages = this.getWatchSPMPackages(platformData);
83
+ await this.applySPMPackagesToTargets(targetNames, platformData, projectData.projectDir, watchSPMPackages);
32
84
  this.$iOSNativeTargetService.prepareSigning(targetUuids, projectData, pbxProjPath);
33
85
  return true;
34
86
  }
87
+ addTarget(targetRootPath, targetFolder, targetType, project, platformData, parentTarget, productTargetType) {
88
+ const targetPath = path.join(targetRootPath, targetFolder);
89
+ const targetRelativePath = path.relative(platformData.projectRoot, targetPath);
90
+ const target = project.addTarget(targetFolder, targetType, targetRelativePath, parentTarget, productTargetType);
91
+ project.addBuildPhase([], "PBXSourcesBuildPhase", "Sources", target.uuid);
92
+ project.addBuildPhase([], "PBXResourcesBuildPhase", "Resources", target.uuid);
93
+ project.addBuildPhase([], "PBXFrameworksBuildPhase", "Frameworks", target.uuid);
94
+ project.addBuildPhase([], "PBXCopyFilesBuildPhase", "Embed Frameworks", target.uuid);
95
+ project.addToHeaderSearchPaths(targetPath, target.pbxNativeTarget.productName);
96
+ return target;
97
+ }
98
+ addSourceFilesFromDirectory(dirPath, targetUuid, project, platformData, groupName, excludePatterns) {
99
+ const items = this.getFolderFiles(dirPath, platformData.projectRoot, excludePatterns);
100
+ for (const item of items) {
101
+ const relativePath = path.relative(platformData.projectRoot, item);
102
+ const ext = path.extname(item).toLowerCase();
103
+ if (sourceExtensions.includes(ext)) {
104
+ this.$logger.debug(`Adding source file: ${relativePath}`);
105
+ this.addSourceFile(project, relativePath, { target: targetUuid }, groupName);
106
+ }
107
+ }
108
+ }
109
+ async addTargetResources(watchAppFolderPath, targetUuids, project, platformData, groupName, excludePatterns) {
110
+ try {
111
+ if (!this.$fs.exists(watchAppFolderPath)) {
112
+ return;
113
+ }
114
+ for (let i = 0; i < targetUuids.length; i++) {
115
+ const targetUuid = targetUuids[i];
116
+ this.addResourcesFromDirectory(watchAppFolderPath, targetUuid, project, platformData, groupName, excludePatterns);
117
+ }
118
+ this.$logger.debug("Watch app resources added successfully");
119
+ }
120
+ catch (err) {
121
+ this.$logger.warn(`Error adding watch app resources: ${err.message}`);
122
+ }
123
+ }
124
+ addResourcesFromDirectory(dirPath, targetUuid, project, platformData, groupName, excludePatterns) {
125
+ const items = this.$fs.readDirectory(dirPath);
126
+ for (const item of items) {
127
+ if (item.startsWith('.') || RESOURCES_TO_IGNORE.indexOf(item) !== -1) {
128
+ continue;
129
+ }
130
+ const itemPath = path.join(dirPath, item);
131
+ const stats = this.$fs.getFsStats(itemPath);
132
+ const relativePath = path.relative(platformData.projectRoot, itemPath);
133
+ if (excludePatterns && this.shouldExclude(relativePath, excludePatterns)) {
134
+ this.$logger.debug(`Excluding from resources: ${relativePath}`);
135
+ continue;
136
+ }
137
+ if (stats.isDirectory()) {
138
+ if (item.endsWith('.xcassets') || item.endsWith('.bundle')) {
139
+ this.$logger.debug(`Adding resource bundle: ${relativePath}`);
140
+ this.addResourceFile(project, relativePath, { target: targetUuid }, groupName);
141
+ }
142
+ else {
143
+ this.addResourcesFromDirectory(itemPath, targetUuid, project, platformData, groupName, excludePatterns);
144
+ }
145
+ }
146
+ else {
147
+ const ext = path.extname(item).toLowerCase();
148
+ if (resourceExtensions.includes(ext)) {
149
+ this.$logger.debug(`Adding resource file: ${relativePath}`);
150
+ this.addResourceFile(project, relativePath, { target: targetUuid }, groupName);
151
+ }
152
+ }
153
+ }
154
+ }
35
155
  removeWatchApp({ pbxProjPath }) {
36
156
  const project = new this.$xcode.project(pbxProjPath);
37
157
  project.parseSync();
@@ -43,23 +163,427 @@ class IOSWatchAppService {
43
163
  const watchAppPath = path.join(projectData.getAppResourcesDirectoryPath(), platformData.normalizedPlatformName, constants_1.IOS_WATCHAPP_FOLDER);
44
164
  return this.$fs.exists(watchAppPath);
45
165
  }
46
- configureTarget(targetName, targetPath, identifier, configurationFileName, target, project) {
47
- const targetConfigurationJsonPath = path.join(targetPath, configurationFileName);
166
+ async configureTarget(targetName, targetPath, identifier, configPath, config, target, project, projectData, platformData, pbxProjPath) {
48
167
  const identifierParts = identifier.split(".");
49
168
  identifierParts.pop();
50
169
  const wkAppBundleIdentifier = identifierParts.join(".");
51
- this.$iOSNativeTargetService.setXcodeTargetBuildConfigurationProperties([
170
+ const buildConfigProperties = [
52
171
  { name: "PRODUCT_BUNDLE_IDENTIFIER", value: identifier },
53
172
  { name: "SDKROOT", value: "watchos" },
54
173
  { name: "TARGETED_DEVICE_FAMILY", value: constants_1.IOSDeviceTargets.watchos },
55
174
  { name: "WATCHOS_DEPLOYMENT_TARGET", value: 5.2 },
56
175
  { name: "WK_APP_BUNDLE_IDENTIFIER", value: wkAppBundleIdentifier },
57
- ], targetName, project);
58
- this.$iOSNativeTargetService.setConfigurationsFromJsonFile(targetConfigurationJsonPath, target.uuid, targetName, project);
176
+ ];
177
+ const resourcesGroup = targetName + "Resources";
178
+ project.addPbxGroup([], resourcesGroup, project.filepath, null, {
179
+ isMain: true,
180
+ target: target.uuid,
181
+ filesRelativeToProject: true,
182
+ });
183
+ const srcGroup = targetName + "Src";
184
+ project.addPbxGroup([], srcGroup, project.filepath, null, {
185
+ isMain: true,
186
+ target: target.uuid,
187
+ filesRelativeToProject: true,
188
+ });
189
+ let basedir;
190
+ if (config === null || config === void 0 ? void 0 : config.basedir) {
191
+ basedir = path.resolve(path.dirname(configPath), config.basedir);
192
+ if (!this.$fs.exists(basedir)) {
193
+ this.$logger.warn(`Basedir not found, using config directory: ${basedir}`);
194
+ basedir = path.dirname(configPath);
195
+ }
196
+ }
197
+ else {
198
+ basedir = path.dirname(configPath);
199
+ }
200
+ const resourcesExclude = (config === null || config === void 0 ? void 0 : config.resourcesExclude) || [];
201
+ const srcExclude = (config === null || config === void 0 ? void 0 : config.srcExclude) || [];
202
+ if (config === null || config === void 0 ? void 0 : config.infoPlistPath) {
203
+ const infoPlistPath = path.resolve(basedir, config.infoPlistPath);
204
+ if (this.$fs.exists(infoPlistPath)) {
205
+ const relativeInfoPlistPath = path.relative(platformData.projectRoot, infoPlistPath);
206
+ buildConfigProperties.push({
207
+ name: "INFOPLIST_FILE",
208
+ value: `"${infoPlistPath}"`
209
+ });
210
+ resourcesExclude.push(relativeInfoPlistPath);
211
+ }
212
+ else {
213
+ this.$logger.warn(`Custom Info.plist not found at: ${infoPlistPath}`);
214
+ }
215
+ }
216
+ if (config === null || config === void 0 ? void 0 : config.xcprivacyPath) {
217
+ const xcprivacyPath = path.resolve(basedir, config.xcprivacyPath);
218
+ if (this.$fs.exists(xcprivacyPath)) {
219
+ const relativeXcprivacyPath = path.relative(platformData.projectRoot, xcprivacyPath);
220
+ this.addResourceFile(project, xcprivacyPath, { target: target.uuid }, targetName + "Resources");
221
+ resourcesExclude.push(relativeXcprivacyPath);
222
+ }
223
+ else {
224
+ this.$logger.warn(`Custom xcprivacy file not found at: ${xcprivacyPath}`);
225
+ }
226
+ }
227
+ this.$iOSNativeTargetService.setXcodeTargetBuildConfigurationProperties(buildConfigProperties, targetName, project);
228
+ this.$iOSNativeTargetService.setConfigurationsFromJsonFile(configPath, target.uuid, targetName, project);
59
229
  project.addToHeaderSearchPaths(targetPath, target.pbxNativeTarget.productName);
230
+ if ((config === null || config === void 0 ? void 0 : config.importSourcesFromMainFolder) !== false) {
231
+ await this.addSourceFilesFromDirectory(path.dirname(configPath), target.uuid, project, platformData, targetName + 'Src', srcExclude);
232
+ }
233
+ if ((config === null || config === void 0 ? void 0 : config.importResourcesFromMainFolder) !== false) {
234
+ await this.addTargetResources(path.dirname(configPath), [target.uuid], project, platformData, resourcesGroup, resourcesExclude);
235
+ }
236
+ if (config) {
237
+ await this.processWatchAppConfiguration(config, basedir, targetName, target, project, projectData, platformData, pbxProjPath, srcExclude, resourcesExclude);
238
+ }
239
+ }
240
+ async processWatchAppConfiguration(config, basedir, targetName, target, project, projectData, platformData, pbxProjPath, srcExclude, resourcesExclude) {
241
+ this.$logger.debug(`processWatchAppConfiguration ${JSON.stringify(config)}`);
242
+ if (config.resources && Array.isArray(config.resources)) {
243
+ this.$logger.debug(`Processing ${config.resources.length} custom resource(s) for watch target: ${targetName}`);
244
+ for (const resourcePath of config.resources) {
245
+ this.addCustomResource(resourcePath, target.uuid, project, projectData, platformData, targetName + "Resources", resourcesExclude, basedir);
246
+ }
247
+ }
248
+ if (config.src && Array.isArray(config.src)) {
249
+ this.$logger.debug(`Processing ${config.src.length} custom source file(s) for watch target: ${targetName}`);
250
+ for (const srcPath of config.src) {
251
+ this.addCustomSourceFile(srcPath, target.uuid, project, projectData, platformData, srcExclude, targetName + 'Src', basedir);
252
+ }
253
+ }
254
+ if (config.SPMPackages && Array.isArray(config.SPMPackages)) {
255
+ this.$fs.writeFile(pbxProjPath, project.writeSync({ omitEmptyValues: true }));
256
+ await this.applySPMPackagesToTargets([targetName], platformData, basedir, config.SPMPackages);
257
+ project.parseSync();
258
+ }
259
+ if (config.modules && Array.isArray(config.modules)) {
260
+ this.$logger.debug(`Processing ${config.modules.length} module(s) for watch target: ${targetName}`);
261
+ for (const moduleDef of config.modules) {
262
+ await this.addModuleDependency(moduleDef, config, targetName, target, project, projectData, platformData, srcExclude, resourcesExclude, basedir);
263
+ }
264
+ }
265
+ }
266
+ addCustomResource(resourcePath, targetUuid, project, projectData, platformData, groupName, excludePatterns, basedir) {
267
+ const resolvedPath = this.resolvePathWithBasedir(resourcePath, basedir, projectData.projectDir);
268
+ if (!this.$fs.exists(resolvedPath)) {
269
+ this.$logger.warn(`Custom resource not found, skipping: ${resourcePath}`);
270
+ return;
271
+ }
272
+ const relativePath = path.relative(platformData.projectRoot, resolvedPath);
273
+ if (excludePatterns && this.shouldExclude(relativePath, excludePatterns)) {
274
+ this.$logger.debug(`Excluding from resources: ${relativePath}`);
275
+ return;
276
+ }
277
+ const stats = this.$fs.getFsStats(resolvedPath);
278
+ if (stats.isDirectory()) {
279
+ this.$logger.debug(`Recursively adding files from resource directory: ${resourcePath}`);
280
+ if (relativePath.endsWith('.xcassets') || relativePath.endsWith('.bundle')) {
281
+ this.$logger.debug(`Adding resource bundle: ${relativePath} for target:${targetUuid}`);
282
+ this.addResourceFile(project, relativePath, { target: targetUuid }, groupName);
283
+ }
284
+ else {
285
+ this.addAllResourcesRecursively(resolvedPath, targetUuid, project, platformData, groupName, excludePatterns);
286
+ }
287
+ }
288
+ else {
289
+ this.$logger.debug(`Adding custom resource file: ${relativePath}`);
290
+ this.addResourceFile(project, relativePath, { target: targetUuid }, groupName);
291
+ }
292
+ }
293
+ addCustomSourceFile(srcPath, targetUuid, project, projectData, platformData, excludePatterns, groupName, basedir) {
294
+ const resolvedPath = this.resolvePathWithBasedir(srcPath, basedir, projectData.projectDir);
295
+ if (!this.$fs.exists(resolvedPath)) {
296
+ this.$logger.warn(`Custom source file/folder not found, skipping: ${srcPath}`);
297
+ return;
298
+ }
299
+ const relativePath = path.relative(platformData.projectRoot, resolvedPath);
300
+ if (excludePatterns && this.shouldExclude(relativePath, excludePatterns)) {
301
+ this.$logger.debug(`Excluding from src: ${relativePath}`);
302
+ return;
303
+ }
304
+ const stats = this.$fs.getFsStats(resolvedPath);
305
+ if (stats.isDirectory()) {
306
+ this.$logger.debug(`Adding custom source directory: ${relativePath}`);
307
+ this.addAllSourceFilesFromDirectory(resolvedPath, targetUuid, project, platformData, groupName, excludePatterns);
308
+ }
309
+ else {
310
+ this.$logger.debug(`Adding custom source file: ${relativePath}`);
311
+ this.addSourceFile(project, relativePath, { target: targetUuid }, groupName);
312
+ }
313
+ }
314
+ resolvePathWithBasedir(relativePath, basedir, fallbackDir) {
315
+ return basedir
316
+ ? path.resolve(basedir, relativePath)
317
+ : path.resolve(fallbackDir, relativePath);
318
+ }
319
+ addAllSourceFilesFromDirectory(dirPath, targetUuid, project, platformData, groupName, excludePatterns) {
320
+ const items = this.getFolderFiles(dirPath, platformData.projectRoot, excludePatterns);
321
+ for (const item of items) {
322
+ const relativePath = path.relative(platformData.projectRoot, item);
323
+ const ext = path.extname(item).toLowerCase();
324
+ if (sourceExtensions.includes(ext)) {
325
+ this.$logger.debug(`Adding source file: ${relativePath}`);
326
+ this.addSourceFile(project, relativePath, { target: targetUuid }, groupName);
327
+ }
328
+ }
329
+ }
330
+ addAllResourcesRecursively(dirPath, targetUuid, project, platformData, groupName, excludePatterns) {
331
+ const items = this.$fs.readDirectory(dirPath);
332
+ for (const item of items) {
333
+ if (item.startsWith('.')) {
334
+ continue;
335
+ }
336
+ const itemPath = path.join(dirPath, item);
337
+ const stats = this.$fs.getFsStats(itemPath);
338
+ const relativePath = path.relative(platformData.projectRoot, itemPath);
339
+ if (excludePatterns && this.shouldExclude(relativePath, excludePatterns)) {
340
+ this.$logger.debug(`Excluding from resources: ${relativePath}`);
341
+ return;
342
+ }
343
+ if (stats.isDirectory()) {
344
+ if (item.endsWith('.xcassets') || item.endsWith('.bundle')) {
345
+ this.$logger.debug(`Adding resource bundle: ${relativePath} for target:${targetUuid}`);
346
+ this.addResourceFile(project, relativePath, { target: targetUuid }, groupName);
347
+ }
348
+ else {
349
+ this.addAllResourcesRecursively(itemPath, targetUuid, project, platformData, groupName, excludePatterns);
350
+ }
351
+ }
352
+ else {
353
+ this.$logger.debug(`Adding resource file: ${relativePath}`);
354
+ this.addResourceFile(project, relativePath, { target: targetUuid }, groupName);
355
+ }
356
+ }
357
+ }
358
+ async addModuleDependency(moduleDef, config, targetName, target, project, projectData, platformData, srcExclude, resourcesExclude, basedir) {
359
+ const modulePath = moduleDef.path
360
+ ? this.resolvePathWithBasedir(moduleDef.path, basedir, projectData.projectDir)
361
+ : null;
362
+ if (!modulePath || !this.$fs.exists(modulePath)) {
363
+ this.$logger.warn(`Module path not found, skipping module: ${modulePath}`);
364
+ return;
365
+ }
366
+ const relativePath = path.relative(platformData.projectRoot, modulePath);
367
+ const stats = this.$fs.getFsStats(modulePath);
368
+ const isFramework = modulePath.endsWith('.framework') || modulePath.endsWith('.xcframework');
369
+ const isFolder = stats.isDirectory() && !isFramework;
370
+ this.$logger.debug(`Adding module dependency: ${JSON.stringify(moduleDef)} to ${targetName}, basedir:${basedir}, isFramework:${isFramework} isFolder:${isFolder}`);
371
+ if (isFramework) {
372
+ this.addCompiledFramework(moduleDef, relativePath, targetName, target, project);
373
+ }
374
+ else if (isFolder) {
375
+ await this.addFolderModule(moduleDef, modulePath, relativePath, targetName, target, config, project, basedir, srcExclude, resourcesExclude, projectData, platformData);
376
+ }
377
+ else {
378
+ this.$logger.warn(`Unknown module type for: ${modulePath}`);
379
+ }
380
+ if (moduleDef.headerSearchPaths && Array.isArray(moduleDef.headerSearchPaths)) {
381
+ for (const headerPath of moduleDef.headerSearchPaths) {
382
+ const resolvedPath = this.resolvePathWithBasedir(headerPath, basedir, projectData.projectDir);
383
+ const relPath = path.relative(platformData.projectRoot, resolvedPath);
384
+ project.addToHeaderSearchPaths(relPath, targetName);
385
+ this.$logger.debug(`Added header search path: ${relPath}`);
386
+ }
387
+ }
388
+ if (moduleDef.linkerFlags && Array.isArray(moduleDef.linkerFlags)) {
389
+ this.addLinkerFlags(moduleDef.linkerFlags, targetName, project);
390
+ }
391
+ }
392
+ addCompiledFramework(moduleDef, relativePath, targetName, target, project) {
393
+ const moduleName = moduleDef.name;
394
+ project.addFramework(relativePath, {
395
+ target: target.uuid,
396
+ customFramework: true,
397
+ embed: moduleDef.embed !== false,
398
+ });
399
+ const frameworkDir = path.dirname(relativePath);
400
+ project.addBuildProperty("FRAMEWORK_SEARCH_PATHS", `"$(inherited)" "${frameworkDir}"`, null, targetName);
401
+ this.$logger.debug(`Added compiled framework ${moduleName} at ${relativePath}`);
402
+ }
403
+ getFolderFiles(dirPath, rootPath, excludePatterns) {
404
+ const result = [];
405
+ const files = this.$fs.readDirectory(dirPath).filter((fileName) => !fileName.startsWith("."));
406
+ for (const item of files) {
407
+ const itemPath = path.join(dirPath, item);
408
+ const stats = this.$fs.getFsStats(itemPath);
409
+ const relativePath = path.relative(rootPath, itemPath);
410
+ if (excludePatterns && this.shouldExclude(relativePath, excludePatterns)) {
411
+ this.$logger.debug(`Excluding from src: ${relativePath}`);
412
+ continue;
413
+ }
414
+ if (stats.isDirectory()) {
415
+ result.push(...this.getFolderFiles(itemPath, rootPath, excludePatterns));
416
+ }
417
+ else {
418
+ result.push(itemPath);
419
+ }
420
+ }
421
+ return result;
422
+ }
423
+ addBuildPhaseIfNotExisting(project, buildPhaseType, comment, target) {
424
+ let buildPhase = project.buildPhaseObject(buildPhaseType, comment, target);
425
+ if (!buildPhase) {
426
+ project.addBuildPhase([], buildPhaseType, comment, target);
427
+ }
428
+ }
429
+ async addFolderModule(moduleDef, modulePath, relativePath, targetName, target, config, project, basedir, srcExclude, resourcesExclude, projectData, platformData) {
430
+ var _a;
431
+ const moduleName = moduleDef.name || path.basename(modulePath);
432
+ const targetRelativePath = path.relative(platformData.projectRoot, modulePath);
433
+ const moduleTarget = project.addTarget(moduleName, (_a = moduleDef.targetType) !== null && _a !== void 0 ? _a : 'framework', targetRelativePath, target.uuid);
434
+ this.$logger.debug(`Adding folder module ${moduleName} with path ${modulePath} with target uuid:${moduleTarget.uuid}`);
435
+ const { path: filePath, name, dependencies, frameworks, buildConfigurationProperties, src, resources, SPMPackages, ...otherProps } = moduleDef;
436
+ project.addFramework(moduleName + '.framework', {
437
+ target: target.uuid,
438
+ basename: moduleName,
439
+ path: moduleName + '.framework',
440
+ customFramework: true,
441
+ explicitFileType: 'wrapper.framework',
442
+ ...otherProps
443
+ });
444
+ project.addBuildPhase([], "PBXSourcesBuildPhase", "Sources", moduleTarget.uuid);
445
+ project.addBuildPhase([], "PBXResourcesBuildPhase", "Resources", moduleTarget.uuid);
446
+ project.addBuildPhase([], "PBXFrameworksBuildPhase", "Frameworks", moduleTarget.uuid);
447
+ project.addBuildPhase([], "PBXCopyFilesBuildPhase", "Embed Frameworks", moduleTarget.uuid);
448
+ const files = this.getFolderFiles(modulePath, platformData.projectRoot, srcExclude);
449
+ this.$logger.debug(`module ${moduleName} has ${files.length} files`);
450
+ if (files.length > 0) {
451
+ project.addPbxGroup(files, moduleName, modulePath, null, {
452
+ isMain: true,
453
+ target: moduleTarget.uuid,
454
+ filesRelativeToProject: true,
455
+ });
456
+ }
457
+ if (moduleDef.frameworks && Array.isArray(moduleDef.frameworks)) {
458
+ this.$logger.debug(`Adding ${moduleDef.frameworks.length} framework(s) for module ${JSON.stringify(moduleDef)}`);
459
+ for (const framework of moduleDef.frameworks) {
460
+ this.$logger.debug(`Adding framework ${JSON.stringify(framework)} for module ${JSON.stringify(moduleDef)}`);
461
+ if (typeof framework === 'string') {
462
+ project.addFramework(framework, { target: moduleTarget.uuid });
463
+ }
464
+ else {
465
+ project.addFramework(framework.path, { target: moduleTarget.uuid, ...framework });
466
+ }
467
+ this.$logger.debug(`Added framework dependency: ${framework}`);
468
+ }
469
+ }
470
+ if (moduleDef.src && Array.isArray(moduleDef.src)) {
471
+ this.$logger.debug(`Processing ${config.src.length} custom source file(s) for target: ${moduleName}`);
472
+ for (const srcPath of moduleDef.src) {
473
+ this.addCustomSourceFile(srcPath, moduleTarget.uuid, project, projectData, platformData, srcExclude, moduleName + 'Src', basedir);
474
+ }
475
+ }
476
+ if (moduleDef.resources && Array.isArray(moduleDef.resources)) {
477
+ this.$logger.debug(`Processing ${moduleDef.resources.length} custom resource(s) for target: ${moduleName}/${moduleTarget.uuid}`);
478
+ for (const resourcePath of moduleDef.resources) {
479
+ this.addCustomResource(resourcePath, moduleTarget.uuid, project, projectData, platformData, targetName + "Resources", resourcesExclude, basedir);
480
+ }
481
+ }
482
+ if (moduleDef.dependencies && Array.isArray(moduleDef.dependencies)) {
483
+ const currentTargets = project.pbxNativeTargetSection();
484
+ const currentTargetsArray = Object.keys(currentTargets).map(k => currentTargets[k]['name'] ? ({ uuid: k, name: currentTargets[k]['name'] }) : null).filter(t => !!t);
485
+ const targets = moduleDef.dependencies.map(dependency => currentTargetsArray.find(t => t.name === `\"${dependency}\"`)).filter(s => !!s);
486
+ if (targets.length) {
487
+ this.$logger.debug(`Adding target dependencies ${moduleDef.dependencies} with uuids:${targets.map(t => t.uuid)} for module ${moduleDef.name}`);
488
+ project.addTargetDependency(moduleTarget.uuid, targets.map(t => t.uuid));
489
+ }
490
+ }
491
+ if (moduleDef.SPMPackages && Array.isArray(moduleDef.SPMPackages)) {
492
+ this.$fs.writeFile(project.filepath, project.writeSync({ omitEmptyValues: true }));
493
+ await this.applySPMPackagesToTargets([moduleName], platformData, basedir, moduleDef.SPMPackages.map(t => {
494
+ if (typeof t === 'string') {
495
+ return config.SPMPackages.find(s => s.name === t);
496
+ }
497
+ return t;
498
+ }));
499
+ project.parseSync();
500
+ }
501
+ if (moduleDef.buildConfigurationProperties || config.sharedModulesBuildConfigurationProperties) {
502
+ const configurationProperties = { ...(config.sharedModulesBuildConfigurationProperties || {}), ...(moduleDef.buildConfigurationProperties || {}) };
503
+ this.$iOSNativeTargetService.setXcodeTargetBuildConfigurationProperties(Object.keys(configurationProperties).map(k => ({ name: k, value: configurationProperties[k] })), moduleName, project);
504
+ }
505
+ this.$logger.debug(`Added folder-based module ${moduleName} at ${relativePath}`);
506
+ }
507
+ addLinkerFlags(flags, targetName, project) {
508
+ for (const flag of flags) {
509
+ const currentFlags = this.getBuildProperty("OTHER_LDFLAGS", targetName, project);
510
+ const flagsArray = currentFlags
511
+ ? (Array.isArray(currentFlags) ? currentFlags : [currentFlags])
512
+ : ['"$(inherited)"'];
513
+ if (!flagsArray.includes(flag)) {
514
+ flagsArray.push(flag);
515
+ }
516
+ project.addBuildProperty("OTHER_LDFLAGS", flagsArray, null, targetName);
517
+ this.$logger.debug(`Added linker flag: ${flag}`);
518
+ }
519
+ }
520
+ getBuildProperty(propertyName, targetName, project) {
521
+ const projectHash = project.hash;
522
+ if (!projectHash) {
523
+ return null;
524
+ }
525
+ const configurations = projectHash.project.objects.XCBuildConfiguration;
526
+ if (!configurations) {
527
+ return null;
528
+ }
529
+ for (const key in configurations) {
530
+ const config = configurations[key];
531
+ if (config && config.buildSettings &&
532
+ (config.buildSettings.PRODUCT_NAME === targetName ||
533
+ config.buildSettings.PRODUCT_NAME === `"${targetName}"`)) {
534
+ return config.buildSettings[propertyName];
535
+ }
536
+ }
537
+ return null;
538
+ }
539
+ shouldExclude(filePath, excludePatterns) {
540
+ for (const pattern of excludePatterns) {
541
+ const matcher = new minimatch_1.Minimatch(pattern, { dot: true });
542
+ if (matcher.match(filePath)) {
543
+ return true;
544
+ }
545
+ }
546
+ return false;
547
+ }
548
+ async applySPMPackagesToTargets(targetNames, platformData, basedir, watchSPMPackages) {
549
+ try {
550
+ this.$logger.debug(`applySPMPackagesToTargets ${JSON.stringify(watchSPMPackages)}`);
551
+ if (watchSPMPackages.length === 0) {
552
+ return;
553
+ }
554
+ this.$logger.debug(`Applying ${watchSPMPackages.length} SPM package(s) to targets:${targetNames}`);
555
+ const project = new trapezedev_project_1.MobileProject(platformData.projectRoot, {
556
+ ios: {
557
+ path: ".",
558
+ },
559
+ enableAndroid: false,
560
+ });
561
+ await project.load();
562
+ if (!project.ios) {
563
+ this.$logger.debug("No iOS project found via trapeze");
564
+ return;
565
+ }
566
+ for (const pkg of watchSPMPackages) {
567
+ if ("path" in pkg) {
568
+ pkg.path = path.resolve(basedir, pkg.path);
569
+ }
570
+ this.$logger.debug(`Adding SPM package ${JSON.stringify(pkg)} to targets ${targetNames}`);
571
+ for (const targetName of targetNames) {
572
+ project.ios.addSPMPackage(targetName, pkg);
573
+ }
574
+ }
575
+ await project.commit();
576
+ this.$logger.debug(`Successfully applied SPM packages to targets ${targetNames}`);
577
+ }
578
+ catch (err) {
579
+ this.$logger.debug(`Error applying SPM packages to targets ${targetNames} "`, err);
580
+ }
581
+ }
582
+ getWatchSPMPackages(platformData) {
583
+ const $projectConfigService = yok_1.injector.resolve("projectConfigService");
584
+ const watchPackages = $projectConfigService.getValue(`${platformData.platformNameLowerCase}.watchApp.SPMPackages`, []);
585
+ return watchPackages;
60
586
  }
61
587
  }
62
588
  exports.IOSWatchAppService = IOSWatchAppService;
63
- IOSWatchAppService.WATCH_APP_IDENTIFIER = "watchkitapp";
64
- IOSWatchAppService.WACTCH_EXTENSION_IDENTIFIER = "watchkitextension";
65
589
  yok_1.injector.register("iOSWatchAppService", IOSWatchAppService);
@@ -292,7 +292,9 @@ class AndroidLivesyncTool {
292
292
  socket.removeAllListeners();
293
293
  this.pendingConnectionData.socketTimer = setTimeout(tryConnect, 1000);
294
294
  };
295
- this.pendingConnectionData.socket = socket;
295
+ if (this.pendingConnectionData) {
296
+ this.pendingConnectionData.socket = socket;
297
+ }
296
298
  socket.once("data", (data) => {
297
299
  socket.removeListener("close", tryConnectAfterTimeout);
298
300
  socket.removeListener("error", tryConnectAfterTimeout);