@akylas/nativescript-cli 8.11.2 → 8.11.3

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.
@@ -84,18 +84,17 @@ class CommandDispatcher {
84
84
  let updateCommand = "";
85
85
  switch (packageManagerName) {
86
86
  case constants_1.PackageManagers.yarn:
87
- case constants_1.PackageManagers.yarn2:
88
- updateCommand = "yarn global add nativescript";
87
+ updateCommand = "yarn global add @akylas/nativescript-cli";
89
88
  break;
90
89
  case constants_1.PackageManagers.pnpm:
91
- updateCommand = "pnpm i -g nativescript";
90
+ updateCommand = "pnpm i -g @akylas/nativescript-cli";
92
91
  break;
93
92
  case constants_1.PackageManagers.bun:
94
- updateCommand = "bun add --global nativescript";
93
+ updateCommand = "bun add --global @akylas/nativescript-cli";
95
94
  break;
96
95
  case constants_1.PackageManagers.npm:
97
96
  default:
98
- updateCommand = "npm i -g nativescript";
97
+ updateCommand = "npm i -g @akylas/nativescript-cli";
99
98
  break;
100
99
  }
101
100
  if (semver.gte(nativescriptCliVersion.currentVersion, nativescriptCliVersion.latestVersion, {
package/lib/constants.js CHANGED
@@ -8,7 +8,7 @@ exports.APP_FOLDER_NAME = "app";
8
8
  exports.APP_RESOURCES_FOLDER_NAME = "App_Resources";
9
9
  exports.PROJECT_FRAMEWORK_FOLDER_NAME = "framework";
10
10
  exports.NS_BASE_PODFILE = "NSPodfileBase";
11
- exports.NATIVESCRIPT_KEY_NAME = "nativescript";
11
+ exports.NATIVESCRIPT_KEY_NAME = "@akylas/nativescript-cli";
12
12
  exports.NODE_MODULES_FOLDER_NAME = "node_modules";
13
13
  exports.TNS_MODULES_FOLDER_NAME = "tns_modules";
14
14
  exports.TNS_CORE_MODULES_NAME = "tns-core-modules";
@@ -211,7 +211,7 @@ class PrepareController extends events_1.EventEmitter {
211
211
  }
212
212
  async getWatcherPatterns(platformData, projectData) {
213
213
  const dependencies = this.$nodeModulesDependenciesBuilder
214
- .getProductionDependencies(projectData.projectDir, projectData.ignoredDependencies)
214
+ .getProductionDependencies(projectData.projectDir, projectData.getIgnoredDependencies(platformData.platformNameLowerCase))
215
215
  .filter((dep) => dep.nativescript);
216
216
  const pluginsNativeDirectories = dependencies.map((dep) => path.join(dep.directory, constants_1.PLATFORMS_DIR_NAME, platformData.platformNameLowerCase));
217
217
  const pluginsPackageJsonFiles = dependencies.map((dep) => path.join(dep.directory, constants_1.PACKAGE_JSON_FILE_NAME));
@@ -233,7 +233,7 @@ class PrepareController extends events_1.EventEmitter {
233
233
  return;
234
234
  }
235
235
  this.$logger.info("Updating runtime package.json with configuration values...");
236
- const { hooks, ignoredNativeDependencies, webpackPackageName, webpackConfigPath, appResourcesPath, buildPath, appPath, ...nsConfig } = this.$projectConfigService.readConfig(projectData.projectDir);
236
+ const { hooks, webpackPackageName, webpackConfigPath, appResourcesPath, buildPath, appPath, ...nsConfig } = this.$projectConfigService.readConfig(projectData.projectDir);
237
237
  const platform = platformData.platformNameLowerCase;
238
238
  let installedRuntimePackageJSON;
239
239
  let runtimePackageName;
@@ -30,4 +30,5 @@ interface IGradleBuildService {
30
30
  interface IGradleBuildArgsService {
31
31
  getBuildTaskArgs(buildData: IAndroidBuildData): Promise<string[]>;
32
32
  getCleanTaskArgs(buildData: IAndroidBuildData): string[];
33
+ getBuildLoggingArgs(): string[];
33
34
  }
@@ -126,6 +126,7 @@ export type BundlerType = "webpack" | "rspack" | "vite";
126
126
  interface INsConfigIOS extends INsConfigPlaform {
127
127
  discardUncaughtJsExceptions?: boolean;
128
128
  runtimePackageName?: string
129
+ ignoredNativeDependencies?: string[];
129
130
  cocoapodUseBundleExec?: boolean
130
131
  /**
131
132
  * Swift Package Manager
@@ -175,9 +176,11 @@ interface INsConfigAndroid extends INsConfigPlaform {
175
176
 
176
177
  gradleArgs?: string[];
177
178
 
178
- plugins?:{ [k:string]: { aarSuffix?: string } }
179
+ plugins?:{ [k:string]: { aarSuffix?: string } };
179
180
 
180
- runtimePackageName?: string
181
+ runtimePackageName?: string;
182
+
183
+ ignoredNativeDependencies?: string[];
181
184
  }
182
185
 
183
186
  interface INsConfigHooks {
@@ -212,7 +215,6 @@ interface IProjectData extends ICreateProjectData {
212
215
  projectId: string;
213
216
  projectIdentifiers?: Mobile.IProjectIdentifier;
214
217
  dependencies: any;
215
- ignoredDependencies?: string[];
216
218
  devDependencies: IStringDictionary;
217
219
  appDirectoryPath: string;
218
220
  appResourcesDirectoryPath: string;
@@ -270,6 +272,7 @@ interface IProjectData extends ICreateProjectData {
270
272
  getAppResourcesDirectoryPath(projectDir?: string): string;
271
273
  getAppResourcesRelativeDirectoryPath(): string;
272
274
  getBuildRelativeDirectoryPath(): string;
275
+ getIgnoredDependencies(platform: string): string[];
273
276
  }
274
277
 
275
278
  interface IProjectDataService {
@@ -908,6 +911,7 @@ interface IWatchAppJSONConfig {
908
911
  basedir?: string;
909
912
  infoPlistPath?: string;
910
913
  xcprivacyPath?: string;
914
+ entitlements?: string;
911
915
  importSourcesFromMainFolder?: boolean;
912
916
  importResourcesFromMainFolder?: boolean;
913
917
  resources?: string[];
@@ -83,7 +83,6 @@ class ProjectData {
83
83
  this.dependencies = packageJsonData.dependencies;
84
84
  this.devDependencies = packageJsonData.devDependencies;
85
85
  this.projectType = this.getProjectType();
86
- this.ignoredDependencies = nsConfig === null || nsConfig === void 0 ? void 0 : nsConfig.ignoredNativeDependencies;
87
86
  this.appDirectoryPath = this.getAppDirectoryPath();
88
87
  this.appResourcesDirectoryPath = this.getAppResourcesDirectoryPath();
89
88
  this.androidManifestPath = this.getPathToAndroidManifest(this.appResourcesDirectoryPath);
@@ -191,6 +190,20 @@ class ProjectData {
191
190
  }
192
191
  return identifier;
193
192
  }
193
+ getIgnoredDependencies(platform) {
194
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
195
+ let ignoredNativeDependencies = (_b = (_a = this.nsConfig) === null || _a === void 0 ? void 0 : _a.ignoredNativeDependencies) !== null && _b !== void 0 ? _b : [];
196
+ if (platform === "visionos") {
197
+ ignoredNativeDependencies = ignoredNativeDependencies.concat((_e = (_d = (_c = this.nsConfig) === null || _c === void 0 ? void 0 : _c.visionos) === null || _d === void 0 ? void 0 : _d.ignoredNativeDependencies) !== null && _e !== void 0 ? _e : []);
198
+ }
199
+ else if (platform === "ios") {
200
+ ignoredNativeDependencies = ignoredNativeDependencies.concat((_h = (_g = (_f = this.nsConfig) === null || _f === void 0 ? void 0 : _f.ios) === null || _g === void 0 ? void 0 : _g.ignoredNativeDependencies) !== null && _h !== void 0 ? _h : []);
201
+ }
202
+ else if (platform === "android") {
203
+ ignoredNativeDependencies = ignoredNativeDependencies.concat((_l = (_k = (_j = this.nsConfig) === null || _j === void 0 ? void 0 : _j.android) === null || _k === void 0 ? void 0 : _k.ignoredNativeDependencies) !== null && _l !== void 0 ? _l : []);
204
+ }
205
+ return ignoredNativeDependencies;
206
+ }
194
207
  getProjectType() {
195
208
  let detectedProjectType = _.find(ProjectData.PROJECT_TYPES, (projectType) => projectType.isDefaultProjectType).type;
196
209
  const deps = _.keys(this.dependencies).concat(_.keys(this.devDependencies));
@@ -36,7 +36,7 @@ class GradleBuildArgsService {
36
36
  projectDir: buildData.projectDir,
37
37
  });
38
38
  this.$projectData.initializeProjectData(buildData.projectDir);
39
- args.push(`--stacktrace`, `-PcompileSdk=${toolsInfo.compileSdkVersion}`, `-PtargetSdk=${toolsInfo.targetSdkVersion}`, `-PbuildToolsVersion=${toolsInfo.buildToolsVersion}`, `-PgenerateTypings=${toolsInfo.generateTypings}`, `-PprojectRoot=${this.$projectData.projectDir}`, `-DprojectRoot=${this.$projectData.projectDir}`, `-PappPath=${this.$projectData.getAppDirectoryPath()}`, `-PappBuildPath=${this.$projectData.getBuildRelativeDirectoryPath()}`, `-DappBuildPath=${this.$projectData.getBuildRelativeDirectoryPath()}`, `-PappPath=${this.$projectData.getAppDirectoryPath()}`, `-PappResourcesPath=${this.$projectData.getAppResourcesDirectoryPath()}`);
39
+ args.push(`-PcompileSdk=${toolsInfo.compileSdkVersion}`, `-PtargetSdk=${toolsInfo.targetSdkVersion}`, `-PbuildToolsVersion=${toolsInfo.buildToolsVersion}`, `-PgenerateTypings=${toolsInfo.generateTypings}`, `-PprojectRoot=${this.$projectData.projectDir}`, `-DprojectRoot=${this.$projectData.projectDir}`, `-PappPath=${this.$projectData.getAppDirectoryPath()}`, `-PappBuildPath=${this.$projectData.getBuildRelativeDirectoryPath()}`, `-DappBuildPath=${this.$projectData.getBuildRelativeDirectoryPath()}`, `-PappPath=${this.$projectData.getAppDirectoryPath()}`, `-PappResourcesPath=${this.$projectData.getAppResourcesDirectoryPath()}`);
40
40
  const gradleArgs = (this.$projectData.nsConfig.android.gradleArgs || []).concat(buildData.gradleArgs || []);
41
41
  if (gradleArgs) {
42
42
  const additionalArgs = [];
@@ -51,17 +51,23 @@ class GradleBuildArgsService {
51
51
  if (buildData.release || buildData.keyStorePath) {
52
52
  args.push(`-PksPath=${path.resolve(buildData.keyStorePath)}`, `-Palias=${buildData.keyStoreAlias}`, `-Ppassword=${buildData.keyStoreAliasPassword}`, `-PksPassword=${buildData.keyStorePassword}`);
53
53
  }
54
+ console.log('getBuildTaskArgs', args);
54
55
  return args;
55
56
  }
56
57
  getBuildLoggingArgs() {
57
58
  const args = [];
58
59
  const logLevel = this.$logger.getLevel();
59
60
  if (logLevel === constants_2.LoggerLevel.TRACE) {
61
+ args.push("--stacktrace");
60
62
  args.push("--debug");
61
63
  }
62
64
  else if (logLevel === constants_2.LoggerLevel.DEBUG) {
65
+ args.push("--stacktrace");
63
66
  args.push("--info");
64
67
  }
68
+ else if (logLevel === constants_2.LoggerLevel.INFO) {
69
+ args.push("--quiet");
70
+ }
65
71
  return args;
66
72
  }
67
73
  getBuildTaskName(buildData) {
@@ -19,7 +19,7 @@ class AndroidPluginBuildService {
19
19
  get $platformsDataService() {
20
20
  return this.$injector.resolve("platformsDataService");
21
21
  }
22
- constructor($fs, $childProcess, $androidToolsInfo, $hostInfo, $options, $logger, $packageManager, $projectData, $projectDataService, $devicePlatformsConstants, $errors, $filesHashService, $hooksService, $injector, $watchIgnoreListService) {
22
+ constructor($fs, $childProcess, $androidToolsInfo, $hostInfo, $options, $logger, $packageManager, $projectData, $projectDataService, $devicePlatformsConstants, $gradleBuildArgsService, $errors, $filesHashService, $hooksService, $injector, $watchIgnoreListService) {
23
23
  this.$fs = $fs;
24
24
  this.$childProcess = $childProcess;
25
25
  this.$androidToolsInfo = $androidToolsInfo;
@@ -30,6 +30,7 @@ class AndroidPluginBuildService {
30
30
  this.$projectData = $projectData;
31
31
  this.$projectDataService = $projectDataService;
32
32
  this.$devicePlatformsConstants = $devicePlatformsConstants;
33
+ this.$gradleBuildArgsService = $gradleBuildArgsService;
33
34
  this.$errors = $errors;
34
35
  this.$filesHashService = $filesHashService;
35
36
  this.$hooksService = $hooksService;
@@ -453,9 +454,7 @@ class AndroidPluginBuildService {
453
454
  });
454
455
  localArgs.push(...additionalArgs);
455
456
  }
456
- if (this.$logger.getLevel() === "INFO") {
457
- localArgs.push("--info");
458
- }
457
+ localArgs.push(...this.$gradleBuildArgsService.getBuildLoggingArgs());
459
458
  const opts = {
460
459
  cwd: pluginBuildSettings.pluginDir,
461
460
  stdio: "inherit",
@@ -4,15 +4,43 @@ exports.IOSExtensionsService = 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 CONFIG_FILE_EXTENSION = "extension.json";
24
+ const RESOURCES_TO_IGNORE = [CONFIG_FILE_EXTENSION, 'node_modules'];
7
25
  class IOSExtensionsService {
8
- constructor($fs, $pbxprojDomXcode, $xcode, $iOSNativeTargetService) {
26
+ constructor($fs, $pbxprojDomXcode, $xcode, $iOSNativeTargetService, $logger) {
9
27
  this.$fs = $fs;
10
28
  this.$pbxprojDomXcode = $pbxprojDomXcode;
11
29
  this.$xcode = $xcode;
12
30
  this.$iOSNativeTargetService = $iOSNativeTargetService;
31
+ this.$logger = $logger;
32
+ }
33
+ addResourceFile(project, path, opt, group = 'ExtensionResources') {
34
+ const file = project.addResourceFile(path, opt, group);
35
+ project.addToResourcesPbxGroup(file, group);
36
+ }
37
+ addSourceFile(project, path, opt, group = 'ExtensionSrc') {
38
+ const file = project.addSourceFile(path, opt, group);
39
+ project.addToResourcesPbxGroup(file, group);
13
40
  }
14
41
  async addExtensionsFromPath({ extensionsFolderPath, projectData, platformData, pbxProjPath, }) {
15
42
  const targetUuids = [];
43
+ const targetNames = [];
16
44
  let addedExtensions = false;
17
45
  if (!this.$fs.exists(extensionsFolderPath)) {
18
46
  return false;
@@ -23,23 +51,507 @@ class IOSExtensionsService {
23
51
  .getTargetDirectories(extensionsFolderPath)
24
52
  .forEach((extensionFolder) => {
25
53
  const target = this.$iOSNativeTargetService.addTargetToProject(extensionsFolderPath, extensionFolder, constants_1.IOSNativeTargetTypes.appExtension, project, platformData);
26
- this.configureTarget(extensionFolder, path.join(extensionsFolderPath, extensionFolder), target, project, projectData);
54
+ const extensionPath = path.join(extensionsFolderPath, extensionFolder);
55
+ const configPath = path.join(extensionPath, CONFIG_FILE_EXTENSION);
56
+ const config = this.$fs.exists(configPath) ? this.$fs.readJson(configPath) : null;
57
+ this.configureTarget(extensionFolder, extensionPath, configPath, config, target, project, projectData, platformData, pbxProjPath);
27
58
  targetUuids.push(target.uuid);
59
+ targetNames.push(extensionFolder);
28
60
  addedExtensions = true;
29
61
  });
30
62
  this.$fs.writeFile(pbxProjPath, project.writeSync({ omitEmptyValues: true }));
63
+ const extensionSPMPackages = this.getExtensionSPMPackages(platformData);
64
+ await this.applySPMPackagesToTargets(targetNames, platformData, projectData.projectDir, extensionSPMPackages);
31
65
  this.$iOSNativeTargetService.prepareSigning(targetUuids, projectData, pbxProjPath);
32
66
  return addedExtensions;
33
67
  }
34
- configureTarget(extensionName, extensionPath, target, project, projectData) {
35
- const extJsonPath = path.join(extensionPath, "extension.json");
36
- this.$iOSNativeTargetService.setXcodeTargetBuildConfigurationProperties([
68
+ async configureTarget(extensionName, extensionPath, configPath, config, target, project, projectData, platformData, pbxProjPath) {
69
+ const resourcesGroup = extensionName + "Resources";
70
+ project.addPbxGroup([], resourcesGroup, project.filepath, null, {
71
+ isMain: true,
72
+ target: target.uuid,
73
+ filesRelativeToProject: true,
74
+ });
75
+ const srcGroup = extensionName + "Src";
76
+ project.addPbxGroup([], srcGroup, project.filepath, null, {
77
+ isMain: true,
78
+ target: target.uuid,
79
+ filesRelativeToProject: true,
80
+ });
81
+ let basedir;
82
+ if (config === null || config === void 0 ? void 0 : config.basedir) {
83
+ basedir = path.resolve(path.dirname(configPath), config.basedir);
84
+ if (!this.$fs.exists(basedir)) {
85
+ this.$logger.warn(`Basedir not found, using config directory: ${basedir}`);
86
+ basedir = path.dirname(configPath);
87
+ }
88
+ }
89
+ else {
90
+ basedir = path.dirname(configPath);
91
+ }
92
+ const resourcesExclude = (config === null || config === void 0 ? void 0 : config.resourcesExclude) || [];
93
+ const srcExclude = (config === null || config === void 0 ? void 0 : config.srcExclude) || [];
94
+ const buildConfigProperties = [
37
95
  {
38
96
  name: "PRODUCT_BUNDLE_IDENTIFIER",
39
97
  value: `${projectData.projectIdentifiers.ios}.${extensionName}`,
40
98
  },
41
- ], extensionName, project);
42
- this.$iOSNativeTargetService.setConfigurationsFromJsonFile(extJsonPath, target.uuid, extensionName, project);
99
+ ];
100
+ if (config === null || config === void 0 ? void 0 : config.infoPlistPath) {
101
+ const infoPlistPath = path.resolve(basedir, config.infoPlistPath);
102
+ if (this.$fs.exists(infoPlistPath)) {
103
+ const relativeInfoPlistPath = path.relative(platformData.projectRoot, infoPlistPath);
104
+ buildConfigProperties.push({
105
+ name: "INFOPLIST_FILE",
106
+ value: `"${relativeInfoPlistPath}"`
107
+ });
108
+ resourcesExclude.push(relativeInfoPlistPath);
109
+ }
110
+ else {
111
+ this.$logger.warn(`Custom Info.plist not found at: ${infoPlistPath}`);
112
+ }
113
+ }
114
+ if (config === null || config === void 0 ? void 0 : config.xcprivacyPath) {
115
+ const xcprivacyPath = path.resolve(basedir, config.xcprivacyPath);
116
+ if (this.$fs.exists(xcprivacyPath)) {
117
+ const relativeXcprivacyPath = path.relative(platformData.projectRoot, xcprivacyPath);
118
+ this.addResourceFile(project, relativeXcprivacyPath, { target: target.uuid }, resourcesGroup);
119
+ resourcesExclude.push(relativeXcprivacyPath);
120
+ }
121
+ else {
122
+ this.$logger.warn(`Custom xcprivacy file not found at: ${xcprivacyPath}`);
123
+ }
124
+ }
125
+ if (config === null || config === void 0 ? void 0 : config.entitlements) {
126
+ const entitlementsPath = path.resolve(basedir, config.entitlements);
127
+ console.log('entitlementsPath', entitlementsPath);
128
+ if (this.$fs.exists(entitlementsPath)) {
129
+ const relativeEntitlementsPath = path.relative(platformData.projectRoot, entitlementsPath);
130
+ buildConfigProperties.push({
131
+ name: "CODE_SIGN_ENTITLEMENTS",
132
+ value: `"${relativeEntitlementsPath}"`
133
+ });
134
+ }
135
+ else {
136
+ this.$logger.warn(`Custom xcprivacy file not found at: ${entitlementsPath}`);
137
+ }
138
+ }
139
+ this.$iOSNativeTargetService.setXcodeTargetBuildConfigurationProperties(buildConfigProperties, extensionName, project);
140
+ this.$iOSNativeTargetService.setConfigurationsFromJsonFile(configPath, target.uuid, extensionName, project);
141
+ project.addToHeaderSearchPaths(extensionPath, target.pbxNativeTarget.productName);
142
+ if ((config === null || config === void 0 ? void 0 : config.importSourcesFromMainFolder) === true) {
143
+ this.addSourceFilesFromDirectory(basedir, target.uuid, project, platformData, srcGroup, srcExclude);
144
+ }
145
+ if ((config === null || config === void 0 ? void 0 : config.importResourcesFromMainFolder) === true) {
146
+ this.addTargetResources(basedir, [target.uuid], project, platformData, resourcesGroup, resourcesExclude);
147
+ }
148
+ if (config) {
149
+ await this.processExtensionConfiguration(config, basedir, extensionName, target, project, projectData, platformData, pbxProjPath, srcExclude, resourcesExclude);
150
+ }
151
+ }
152
+ async processExtensionConfiguration(config, basedir, extensionName, target, project, projectData, platformData, pbxProjPath, srcExclude, resourcesExclude) {
153
+ this.$logger.debug(`processExtensionConfiguration ${JSON.stringify(config)}`);
154
+ if (config.resources && Array.isArray(config.resources)) {
155
+ this.$logger.debug(`Processing ${config.resources.length} custom resource(s) for extension target: ${extensionName}`);
156
+ for (const resourcePath of config.resources) {
157
+ this.addCustomResource(resourcePath, target.uuid, project, projectData, platformData, extensionName + "Resources", resourcesExclude, basedir);
158
+ }
159
+ }
160
+ if (config.src && Array.isArray(config.src)) {
161
+ this.$logger.debug(`Processing ${config.src.length} custom source file(s) for extension target: ${extensionName}`);
162
+ for (const srcPath of config.src) {
163
+ this.addCustomSourceFile(srcPath, target.uuid, project, projectData, platformData, srcExclude, extensionName + 'Src', basedir);
164
+ }
165
+ }
166
+ if (config.SPMPackages && Array.isArray(config.SPMPackages)) {
167
+ this.$fs.writeFile(pbxProjPath, project.writeSync({ omitEmptyValues: true }));
168
+ await this.applySPMPackagesToTargets([extensionName], platformData, basedir, config.SPMPackages);
169
+ project.parseSync();
170
+ }
171
+ if (config.modules && Array.isArray(config.modules)) {
172
+ this.$logger.debug(`Processing ${config.modules.length} module(s) for extension target: ${extensionName}`);
173
+ for (const moduleDef of config.modules) {
174
+ await this.addModuleDependency(moduleDef, config, extensionName, target, project, projectData, platformData, srcExclude, resourcesExclude, basedir);
175
+ }
176
+ }
177
+ }
178
+ addSourceFilesFromDirectory(dirPath, targetUuid, project, platformData, groupName, excludePatterns) {
179
+ const items = this.getFolderFiles(dirPath, platformData.projectRoot, excludePatterns);
180
+ for (const item of items) {
181
+ const relativePath = path.relative(platformData.projectRoot, item);
182
+ const ext = path.extname(item).toLowerCase();
183
+ if (sourceExtensions.includes(ext)) {
184
+ this.$logger.debug(`Adding source file: ${relativePath}`);
185
+ this.addSourceFile(project, relativePath, { target: targetUuid }, groupName);
186
+ }
187
+ }
188
+ }
189
+ addTargetResources(folderPath, targetUuids, project, platformData, groupName, excludePatterns) {
190
+ try {
191
+ if (!this.$fs.exists(folderPath)) {
192
+ return;
193
+ }
194
+ for (const targetUuid of targetUuids) {
195
+ this.addResourcesFromDirectory(folderPath, targetUuid, project, platformData, groupName, excludePatterns);
196
+ }
197
+ this.$logger.debug("Extension resources added successfully");
198
+ }
199
+ catch (err) {
200
+ this.$logger.warn(`Error adding extension resources: ${err.message}`);
201
+ }
202
+ }
203
+ addResourcesFromDirectory(dirPath, targetUuid, project, platformData, groupName, excludePatterns) {
204
+ const items = this.$fs.readDirectory(dirPath);
205
+ for (const item of items) {
206
+ if (item.startsWith('.') || RESOURCES_TO_IGNORE.indexOf(item) !== -1) {
207
+ continue;
208
+ }
209
+ const itemPath = path.join(dirPath, item);
210
+ const stats = this.$fs.getFsStats(itemPath);
211
+ const relativePath = path.relative(platformData.projectRoot, itemPath);
212
+ if (excludePatterns && this.shouldExclude(relativePath, excludePatterns)) {
213
+ this.$logger.debug(`Excluding from resources: ${relativePath}`);
214
+ continue;
215
+ }
216
+ if (stats.isDirectory()) {
217
+ if (item.endsWith('.xcassets') || item.endsWith('.bundle')) {
218
+ this.$logger.debug(`Adding resource bundle: ${relativePath}`);
219
+ this.addResourceFile(project, relativePath, { target: targetUuid }, groupName);
220
+ }
221
+ else {
222
+ this.addResourcesFromDirectory(itemPath, targetUuid, project, platformData, groupName, excludePatterns);
223
+ }
224
+ }
225
+ else {
226
+ const ext = path.extname(item).toLowerCase();
227
+ if (resourceExtensions.includes(ext)) {
228
+ this.$logger.debug(`Adding resource file: ${relativePath}`);
229
+ this.addResourceFile(project, relativePath, { target: targetUuid }, groupName);
230
+ }
231
+ }
232
+ }
233
+ }
234
+ addCustomResource(resourcePath, targetUuid, project, projectData, platformData, groupName, excludePatterns, basedir) {
235
+ const resolvedPath = this.resolvePathWithBasedir(resourcePath, basedir, projectData.projectDir);
236
+ if (!this.$fs.exists(resolvedPath)) {
237
+ this.$logger.warn(`Custom resource not found, skipping: ${resourcePath}`);
238
+ return;
239
+ }
240
+ const relativePath = path.relative(platformData.projectRoot, resolvedPath);
241
+ if (excludePatterns && this.shouldExclude(relativePath, excludePatterns)) {
242
+ this.$logger.debug(`Excluding from resources: ${relativePath}`);
243
+ return;
244
+ }
245
+ const stats = this.$fs.getFsStats(resolvedPath);
246
+ if (stats.isDirectory()) {
247
+ if (relativePath.endsWith('.xcassets') || relativePath.endsWith('.bundle')) {
248
+ this.$logger.debug(`Adding resource bundle: ${relativePath} for target:${targetUuid}`);
249
+ this.addResourceFile(project, relativePath, { target: targetUuid }, groupName);
250
+ }
251
+ else {
252
+ this.addAllResourcesRecursively(resolvedPath, targetUuid, project, platformData, groupName, excludePatterns);
253
+ }
254
+ }
255
+ else {
256
+ this.$logger.debug(`Adding custom resource file: ${relativePath}`);
257
+ this.addResourceFile(project, relativePath, { target: targetUuid }, groupName);
258
+ }
259
+ }
260
+ addCustomSourceFile(srcPath, targetUuid, project, projectData, platformData, excludePatterns, groupName, basedir) {
261
+ const resolvedPath = this.resolvePathWithBasedir(srcPath, basedir, projectData.projectDir);
262
+ if (!this.$fs.exists(resolvedPath)) {
263
+ this.$logger.warn(`Custom source file/folder not found, skipping: ${srcPath}`);
264
+ return;
265
+ }
266
+ const relativePath = path.relative(platformData.projectRoot, resolvedPath);
267
+ if (excludePatterns && this.shouldExclude(relativePath, excludePatterns)) {
268
+ this.$logger.debug(`Excluding from src: ${relativePath}`);
269
+ return;
270
+ }
271
+ const stats = this.$fs.getFsStats(resolvedPath);
272
+ if (stats.isDirectory()) {
273
+ this.$logger.debug(`Adding custom source directory: ${relativePath}`);
274
+ this.addAllSourceFilesFromDirectory(resolvedPath, targetUuid, project, platformData, groupName, excludePatterns);
275
+ }
276
+ else {
277
+ this.$logger.debug(`Adding custom source file: ${relativePath}`);
278
+ this.addSourceFile(project, relativePath, { target: targetUuid }, groupName);
279
+ }
280
+ }
281
+ addAllSourceFilesFromDirectory(dirPath, targetUuid, project, platformData, groupName, excludePatterns) {
282
+ const items = this.getFolderFiles(dirPath, platformData.projectRoot, excludePatterns);
283
+ for (const item of items) {
284
+ const relativePath = path.relative(platformData.projectRoot, item);
285
+ const ext = path.extname(item).toLowerCase();
286
+ if (sourceExtensions.includes(ext)) {
287
+ this.$logger.debug(`Adding source file: ${relativePath}`);
288
+ this.addSourceFile(project, relativePath, { target: targetUuid }, groupName);
289
+ }
290
+ }
291
+ }
292
+ addAllResourcesRecursively(dirPath, targetUuid, project, platformData, groupName, excludePatterns) {
293
+ const items = this.$fs.readDirectory(dirPath);
294
+ for (const item of items) {
295
+ if (item.startsWith('.')) {
296
+ continue;
297
+ }
298
+ const itemPath = path.join(dirPath, item);
299
+ const stats = this.$fs.getFsStats(itemPath);
300
+ const relativePath = path.relative(platformData.projectRoot, itemPath);
301
+ if (excludePatterns && this.shouldExclude(relativePath, excludePatterns)) {
302
+ this.$logger.debug(`Excluding from resources: ${relativePath}`);
303
+ return;
304
+ }
305
+ if (stats.isDirectory()) {
306
+ if (item.endsWith('.xcassets') || item.endsWith('.bundle')) {
307
+ this.$logger.debug(`Adding resource bundle: ${relativePath} for target:${targetUuid}`);
308
+ this.addResourceFile(project, relativePath, { target: targetUuid }, groupName);
309
+ }
310
+ else {
311
+ this.addAllResourcesRecursively(itemPath, targetUuid, project, platformData, groupName, excludePatterns);
312
+ }
313
+ }
314
+ else {
315
+ this.$logger.debug(`Adding resource file: ${relativePath}`);
316
+ this.addResourceFile(project, relativePath, { target: targetUuid }, groupName);
317
+ }
318
+ }
319
+ }
320
+ async addModuleDependency(moduleDef, config, targetName, target, project, projectData, platformData, srcExclude, resourcesExclude, basedir) {
321
+ const modulePath = moduleDef.path
322
+ ? this.resolvePathWithBasedir(moduleDef.path, basedir, projectData.projectDir)
323
+ : null;
324
+ if (!modulePath || !this.$fs.exists(modulePath)) {
325
+ this.$logger.warn(`Module path not found, skipping module: ${modulePath}`);
326
+ return;
327
+ }
328
+ const relativePath = path.relative(platformData.projectRoot, modulePath);
329
+ const stats = this.$fs.getFsStats(modulePath);
330
+ const isFramework = modulePath.endsWith('.framework') || modulePath.endsWith('.xcframework');
331
+ const isFolder = stats.isDirectory() && !isFramework;
332
+ if (isFramework) {
333
+ this.addCompiledFramework(moduleDef, relativePath, targetName, target, project);
334
+ }
335
+ else if (isFolder) {
336
+ await this.addFolderModule(moduleDef, modulePath, relativePath, targetName, target, config, project, basedir, srcExclude, resourcesExclude, projectData, platformData);
337
+ }
338
+ else {
339
+ this.$logger.warn(`Unknown module type for: ${modulePath}`);
340
+ }
341
+ if (moduleDef.headerSearchPaths && Array.isArray(moduleDef.headerSearchPaths)) {
342
+ for (const headerPath of moduleDef.headerSearchPaths) {
343
+ const resolvedPath = this.resolvePathWithBasedir(headerPath, basedir, projectData.projectDir);
344
+ const relPath = path.relative(platformData.projectRoot, resolvedPath);
345
+ project.addToHeaderSearchPaths(relPath, targetName);
346
+ this.$logger.debug(`Added header search path: ${relPath}`);
347
+ }
348
+ }
349
+ if (moduleDef.linkerFlags && Array.isArray(moduleDef.linkerFlags)) {
350
+ this.addLinkerFlags(moduleDef.linkerFlags, targetName, project);
351
+ }
352
+ }
353
+ addCompiledFramework(moduleDef, relativePath, targetName, target, project) {
354
+ const moduleName = moduleDef.name;
355
+ project.addFramework(relativePath, {
356
+ target: target.uuid,
357
+ customFramework: true,
358
+ embed: moduleDef.embed !== false,
359
+ });
360
+ const frameworkDir = path.dirname(relativePath);
361
+ project.addBuildProperty("FRAMEWORK_SEARCH_PATHS", `"$(inherited)" "${frameworkDir}"`, null, targetName);
362
+ this.$logger.debug(`Added compiled framework ${moduleName} at ${relativePath}`);
363
+ }
364
+ async addFolderModule(moduleDef, modulePath, relativePath, targetName, target, config, project, basedir, srcExclude, resourcesExclude, projectData, platformData) {
365
+ var _a;
366
+ const moduleName = moduleDef.name || path.basename(modulePath);
367
+ const targetRelativePath = path.relative(platformData.projectRoot, modulePath);
368
+ const moduleTarget = project.addTarget(moduleName, (_a = moduleDef.targetType) !== null && _a !== void 0 ? _a : 'framework', targetRelativePath, target.uuid);
369
+ const { path: filePath, name, dependencies, frameworks, buildConfigurationProperties, src, resources, SPMPackages, ...otherProps } = moduleDef;
370
+ project.addFramework(moduleName + '.framework', {
371
+ target: target.uuid,
372
+ basename: moduleName,
373
+ path: moduleName + '.framework',
374
+ customFramework: true,
375
+ explicitFileType: 'wrapper.framework',
376
+ ...otherProps
377
+ });
378
+ project.addBuildPhase([], "PBXSourcesBuildPhase", "Sources", moduleTarget.uuid);
379
+ project.addBuildPhase([], "PBXResourcesBuildPhase", "Resources", moduleTarget.uuid);
380
+ project.addBuildPhase([], "PBXFrameworksBuildPhase", "Frameworks", moduleTarget.uuid);
381
+ project.addBuildPhase([], "PBXCopyFilesBuildPhase", "Embed Frameworks", moduleTarget.uuid);
382
+ const files = this.getFolderFiles(modulePath, platformData.projectRoot, srcExclude);
383
+ if (files.length > 0) {
384
+ project.addPbxGroup(files, moduleName, modulePath, null, {
385
+ isMain: true,
386
+ target: moduleTarget.uuid,
387
+ filesRelativeToProject: true,
388
+ });
389
+ }
390
+ const moduleSpmPackages = moduleDef.SPMPackages;
391
+ if (moduleDef.frameworks && Array.isArray(moduleDef.frameworks)) {
392
+ for (const framework of moduleDef.frameworks) {
393
+ const frameworkName = typeof framework === 'string' ? framework : framework.path;
394
+ const isSpmProduct = Array.isArray(moduleSpmPackages) && moduleSpmPackages.some((p) => {
395
+ var _a;
396
+ const pkg = typeof p === 'string' ? (_a = config.SPMPackages) === null || _a === void 0 ? void 0 : _a.find(s => s.name === p) : p;
397
+ return pkg && Array.isArray(pkg.libs) && pkg.libs.includes(frameworkName);
398
+ });
399
+ if (isSpmProduct) {
400
+ this.$logger.debug(`Skipping framework ${frameworkName} because it is provided by SPM package`);
401
+ continue;
402
+ }
403
+ if (typeof framework === 'string') {
404
+ project.addFramework(framework, { target: moduleTarget.uuid });
405
+ }
406
+ else {
407
+ project.addFramework(framework.path, { target: moduleTarget.uuid, ...framework });
408
+ }
409
+ }
410
+ }
411
+ if (moduleDef.src && Array.isArray(moduleDef.src)) {
412
+ for (const srcPath of moduleDef.src) {
413
+ this.addCustomSourceFile(srcPath, moduleTarget.uuid, project, projectData, platformData, srcExclude, moduleName + 'Src', basedir);
414
+ }
415
+ }
416
+ if (moduleDef.resources && Array.isArray(moduleDef.resources)) {
417
+ for (const resourcePath of moduleDef.resources) {
418
+ this.addCustomResource(resourcePath, moduleTarget.uuid, project, projectData, platformData, moduleName + "Resources", resourcesExclude, basedir);
419
+ }
420
+ }
421
+ if (moduleDef.dependencies && Array.isArray(moduleDef.dependencies)) {
422
+ const currentTargets = project.pbxNativeTargetSection();
423
+ const currentTargetsArray = Object.keys(currentTargets)
424
+ .map(k => currentTargets[k]['name'] ? ({ uuid: k, name: currentTargets[k]['name'] }) : null)
425
+ .filter(t => !!t);
426
+ const targets = moduleDef.dependencies
427
+ .map(dependency => currentTargetsArray.find(t => t.name === `\"${dependency}\"`))
428
+ .filter(s => !!s);
429
+ if (targets.length) {
430
+ project.addTargetDependency(moduleTarget.uuid, targets.map(t => t.uuid));
431
+ }
432
+ }
433
+ if (moduleDef.SPMPackages && Array.isArray(moduleDef.SPMPackages)) {
434
+ this.$fs.writeFile(project.filepath, project.writeSync({ omitEmptyValues: true }));
435
+ await this.applySPMPackagesToTargets([moduleName], platformData, basedir, moduleDef.SPMPackages.map(t => {
436
+ var _a;
437
+ if (typeof t === 'string') {
438
+ return (_a = config.SPMPackages) === null || _a === void 0 ? void 0 : _a.find(s => s.name === t);
439
+ }
440
+ return t;
441
+ }));
442
+ project.parseSync();
443
+ }
444
+ if (moduleDef.buildConfigurationProperties || config.sharedModulesBuildConfigurationProperties) {
445
+ const configurationProperties = {
446
+ ...(config.sharedModulesBuildConfigurationProperties || {}),
447
+ ...(moduleDef.buildConfigurationProperties || {})
448
+ };
449
+ this.$iOSNativeTargetService.setXcodeTargetBuildConfigurationProperties(Object.keys(configurationProperties).map(k => ({ name: k, value: configurationProperties[k] })), moduleName, project);
450
+ }
451
+ this.$logger.debug(`Added folder-based module ${moduleName} at ${relativePath}`);
452
+ }
453
+ addLinkerFlags(flags, targetName, project) {
454
+ for (const flag of flags) {
455
+ const currentFlags = this.getBuildProperty("OTHER_LDFLAGS", targetName, project);
456
+ const flagsArray = currentFlags
457
+ ? (Array.isArray(currentFlags) ? currentFlags : [currentFlags])
458
+ : ['"$(inherited)"'];
459
+ if (!flagsArray.includes(flag)) {
460
+ flagsArray.push(flag);
461
+ }
462
+ project.addBuildProperty("OTHER_LDFLAGS", flagsArray, null, targetName);
463
+ this.$logger.debug(`Added linker flag: ${flag}`);
464
+ }
465
+ }
466
+ getBuildProperty(propertyName, targetName, project) {
467
+ const projectHash = project.hash;
468
+ if (!projectHash) {
469
+ return null;
470
+ }
471
+ const configurations = projectHash.project.objects.XCBuildConfiguration;
472
+ if (!configurations) {
473
+ return null;
474
+ }
475
+ for (const key in configurations) {
476
+ const config = configurations[key];
477
+ if (config && config.buildSettings &&
478
+ (config.buildSettings.PRODUCT_NAME === targetName ||
479
+ config.buildSettings.PRODUCT_NAME === `"${targetName}"`)) {
480
+ return config.buildSettings[propertyName];
481
+ }
482
+ }
483
+ return null;
484
+ }
485
+ resolvePathWithBasedir(relativePath, basedir, fallbackDir) {
486
+ return basedir
487
+ ? path.resolve(basedir, relativePath)
488
+ : path.resolve(fallbackDir, relativePath);
489
+ }
490
+ getFolderFiles(dirPath, rootPath, excludePatterns) {
491
+ const result = [];
492
+ const files = this.$fs.readDirectory(dirPath).filter((fileName) => !fileName.startsWith("."));
493
+ for (const item of files) {
494
+ const itemPath = path.join(dirPath, item);
495
+ const stats = this.$fs.getFsStats(itemPath);
496
+ const relativePath = path.relative(rootPath, itemPath);
497
+ if (excludePatterns && this.shouldExclude(relativePath, excludePatterns)) {
498
+ this.$logger.debug(`Excluding from src: ${relativePath}`);
499
+ continue;
500
+ }
501
+ if (stats.isDirectory()) {
502
+ result.push(...this.getFolderFiles(itemPath, rootPath, excludePatterns));
503
+ }
504
+ else {
505
+ result.push(itemPath);
506
+ }
507
+ }
508
+ return result;
509
+ }
510
+ shouldExclude(filePath, excludePatterns) {
511
+ for (const pattern of excludePatterns) {
512
+ const matcher = new minimatch_1.Minimatch(pattern, { dot: true });
513
+ if (matcher.match(filePath)) {
514
+ return true;
515
+ }
516
+ }
517
+ return false;
518
+ }
519
+ async applySPMPackagesToTargets(targetNames, platformData, basedir, spmPackages) {
520
+ try {
521
+ if (spmPackages.length === 0) {
522
+ return;
523
+ }
524
+ this.$logger.debug(`Applying ${spmPackages.length} SPM package(s) to targets:${targetNames}`);
525
+ const project = new trapezedev_project_1.MobileProject(platformData.projectRoot, {
526
+ ios: {
527
+ path: ".",
528
+ },
529
+ enableAndroid: false,
530
+ });
531
+ await project.load();
532
+ if (!project.ios) {
533
+ this.$logger.debug("No iOS project found via trapeze");
534
+ return;
535
+ }
536
+ for (const pkg of spmPackages) {
537
+ if ("path" in pkg) {
538
+ pkg.path = path.resolve(basedir, pkg.path);
539
+ }
540
+ for (const targetName of targetNames) {
541
+ project.ios.addSPMPackage(targetName, pkg);
542
+ }
543
+ }
544
+ await project.commit();
545
+ this.$logger.debug(`Successfully applied SPM packages to targets ${targetNames}`);
546
+ }
547
+ catch (err) {
548
+ this.$logger.debug(`Error applying SPM packages to targets ${targetNames}`, err);
549
+ }
550
+ }
551
+ getExtensionSPMPackages(platformData) {
552
+ const $projectConfigService = yok_1.injector.resolve("projectConfigService");
553
+ const extensionPackages = $projectConfigService.getValue(`${platformData.platformNameLowerCase}.extensions.SPMPackages`, []);
554
+ return extensionPackages;
43
555
  }
44
556
  removeExtensions({ pbxProjPath }) {
45
557
  const project = new this.$xcode.project(pbxProjPath);
@@ -159,7 +159,7 @@ class PluginsService {
159
159
  getAllProductionPlugins(projectData, platform, dependencies) {
160
160
  dependencies =
161
161
  dependencies ||
162
- this.$nodeModulesDependenciesBuilder.getProductionDependencies(projectData.projectDir, projectData.ignoredDependencies);
162
+ this.$nodeModulesDependenciesBuilder.getProductionDependencies(projectData.projectDir, projectData.getIgnoredDependencies(platform));
163
163
  if (_.isEmpty(dependencies)) {
164
164
  return [];
165
165
  }
@@ -51,7 +51,7 @@ class ProjectChangesService {
51
51
  }
52
52
  this._changesInfo.appResourcesChanged = this.containsNewerFiles(platformResourcesDir, projectData);
53
53
  this.$nodeModulesDependenciesBuilder
54
- .getProductionDependencies(projectData.projectDir, projectData.ignoredDependencies)
54
+ .getProductionDependencies(projectData.projectDir, projectData.getIgnoredDependencies(platformData.platformNameLowerCase))
55
55
  .filter((dep) => dep.nativescript &&
56
56
  this.$fs.exists(path.join(dep.directory, constants_1.PLATFORMS_DIR_NAME, platformData.platformNameLowerCase)))
57
57
  .forEach((dep) => {
@@ -10,7 +10,7 @@ class NodeModulesBuilder {
10
10
  this.$pluginsService = $pluginsService;
11
11
  }
12
12
  async prepareNodeModules({ platformData, projectData, }) {
13
- let dependencies = this.$nodeModulesDependenciesBuilder.getProductionDependencies(projectData.projectDir, projectData.ignoredDependencies);
13
+ let dependencies = this.$nodeModulesDependenciesBuilder.getProductionDependencies(projectData.projectDir, projectData.getIgnoredDependencies(platformData.platformNameLowerCase));
14
14
  dependencies = await platformData.platformProjectService.beforePrepareAllPlugins(projectData, dependencies);
15
15
  const pluginsData = this.$pluginsService.getAllProductionPlugins(projectData, platformData.platformNameLowerCase, dependencies);
16
16
  if (_.isEmpty(pluginsData)) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@akylas/nativescript-cli",
3
3
  "main": "./lib/nativescript-cli-lib.js",
4
- "version": "8.11.2",
4
+ "version": "8.11.3",
5
5
  "author": "NativeScript <oss@nativescript.org>",
6
6
  "description": "Command-line interface for building NativeScript projects",
7
7
  "bin": {
@@ -191,6 +191,10 @@ buildscript {
191
191
  def pluginData = appDependencies.find { it.name == project.ext.PLUGIN_NAME }
192
192
  project.ext.nativescriptDependencies = appDependencies.findAll{pluginData.dependencies.contains(it.name)}.plus([pluginData])
193
193
  }
194
+
195
+ initialize()
196
+ project.ext.applyBeforePluginGradleConfiguration()
197
+
194
198
  def applyBuildScriptConfigurations = { ->
195
199
  def absolutePathToAppResources = project.ext.getAppResourcesPath()
196
200
  def pathToBuildScriptGradle = "$absolutePathToAppResources/Android/buildscript.gradle"
@@ -223,8 +227,6 @@ buildscript {
223
227
  }
224
228
  }
225
229
 
226
- initialize()
227
- project.ext.applyBeforePluginGradleConfiguration()
228
230
  applyBuildScriptConfigurations()
229
231
 
230
232
  def computeKotlinVersion = { -> project.hasProperty("kotlinVersion") ? kotlinVersion : "${ns_default_kotlin_version}" }