Skip to content

Commit 663736e

Browse files
committed
Add platform specific app identifier in package.json.
Rename projectId to projectIdentifiers. projectId is left as getter and setter to avoid breaking change in hooks and CLI extensions Fix ui tests for platform service and safeguard missing id. Remove breaking change from debug data. Use IProjectDefinition from mobile-cli-lib Fix comments. Fix comments chore: send projectDir instead of projectData to PluginVariableService. chore: fix comments chore: fix tests
1 parent 7a780b9 commit 663736e

26 files changed

+196
-102
lines changed

lib/commands/debug.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,10 @@ export class DebugPlatformCommand implements ICommand {
2424
public async execute(args: string[]): Promise<void> {
2525
const debugOptions = <IDebugOptions>_.cloneDeep(this.$options.argv);
2626

27-
const debugData = this.$debugDataService.createDebugData(this.$projectData, this.$options);
28-
2927
await this.$platformService.trackProjectType(this.$projectData);
3028
const selectedDeviceForDebug = await this.getDeviceForDebug();
31-
debugData.deviceIdentifier = selectedDeviceForDebug.deviceInfo.identifier;
29+
30+
const debugData = this.$debugDataService.createDebugData(this.$projectData, {device: selectedDeviceForDebug.deviceInfo.identifier});
3231

3332
if (this.$options.start) {
3433
await this.$liveSyncService.printDebugInformation(await this.$debugService.debug(debugData, debugOptions));

lib/definitions/livesync.d.ts

+11
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,24 @@ interface ILiveSyncInfo extends IProjectDir, IEnvOptions, IBundle, IRelease, IOp
161161
timeout: string;
162162
}
163163

164+
164165
interface IHasUseHotModuleReloadOption {
165166
/**
166167
* Defines if the hot module reload should be used.
167168
*/
168169
useHotModuleReload?: boolean;
169170
}
170171

172+
interface ILiveSyncEventData {
173+
deviceIdentifier: string,
174+
applicationIdentifier?: string,
175+
projectDir: string,
176+
syncedFiles?: Object
177+
error? : Error,
178+
notification?: string,
179+
isFullSync?: boolean
180+
}
181+
171182
interface ILatestAppPackageInstalledSettings extends IDictionary<IDictionary<boolean>> { /* empty */ }
172183

173184
interface IIsEmulator {

lib/definitions/plugins.d.ts

+8-9
Original file line numberDiff line numberDiff line change
@@ -49,40 +49,39 @@ interface IPluginVariablesService {
4949
/**
5050
* Saves plugin variables in project package.json file.
5151
* @param {IPluginData} pluginData for the plugin.
52-
* @param {IProjectData} projectData DTO with information about the project.
52+
* @param {string} projectDir: Specifies the directory of the project.
5353
* @return {Promise<void>}
5454
*/
55-
savePluginVariablesInProjectFile(pluginData: IPluginData, projectData: IProjectData): Promise<void>;
55+
savePluginVariablesInProjectFile(pluginData: IPluginData, projectDir: string): Promise<void>;
5656

5757
/**
5858
* Removes plugin variables from project package.json file.
5959
* @param {string} pluginName Name of the plugin.
60-
* @param {IProjectData} projectData DTO with information about the project.
60+
* @param {string} projectDir: Specifies the directory of the project.
6161
* @return {void}
6262
*/
63-
removePluginVariablesFromProjectFile(pluginName: string, projectData: IProjectData): void;
63+
removePluginVariablesFromProjectFile(pluginName: string, projectDir: string): void;
6464

6565
/**
6666
* Replaces all plugin variables with their corresponding values.
6767
* @param {IPluginData} pluginData for the plugin.
6868
* @param {pluginConfigurationFilePath} pluginConfigurationFilePath for the plugin.
69-
* @param {IProjectData} projectData DTO with information about the project.
69+
* @param {string} projectDir: Specifies the directory of the project.
7070
* @return {Promise<void>}
7171
*/
72-
interpolatePluginVariables(pluginData: IPluginData, pluginConfigurationFilePath: string, projectData: IProjectData): Promise<void>;
72+
interpolatePluginVariables(pluginData: IPluginData, pluginConfigurationFilePath: string, projectDir: string): Promise<void>;
7373

7474
/**
7575
* Replaces {nativescript.id} expression with the application identifier from package.json.
7676
* @param {pluginConfigurationFilePath} pluginConfigurationFilePath for the plugin.
77-
* @param {IProjectData} projectData DTO with information about the project.
7877
* @return {void}
7978
*/
80-
interpolateAppIdentifier(pluginConfigurationFilePath: string, projectData: IProjectData): void;
79+
interpolateAppIdentifier(pluginConfigurationFilePath: string, projectIdentifier: string): void;
8180

8281
/**
8382
* Replaces both plugin variables and appIdentifier
8483
*/
85-
interpolate(pluginData: IPluginData, pluginConfigurationFilePath: string, projectData: IProjectData): Promise<void>;
84+
interpolate(pluginData: IPluginData, pluginConfigurationFilePath: string, projectDir: string, projectIdentifier: string): Promise<void>;
8685

8786
/**
8887
* Returns the

lib/definitions/project.d.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ interface INsConfig {
7777
interface IProjectData extends ICreateProjectData {
7878
platformsDir: string;
7979
projectFilePath: string;
80-
projectId?: string;
80+
projectId: string;
81+
projectIdentifiers?: Mobile.IProjectIdentifier;
8182
dependencies: any;
8283
devDependencies: IStringDictionary;
8384
appDirectoryPath: string;

lib/helpers/livesync-command-helper.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,15 @@ export class LiveSyncCommandHelper implements ILiveSyncCommandHelper {
162162
};
163163

164164
await this.$platformService.deployPlatform(deployPlatformInfo);
165-
await this.$platformService.startApplication(currentPlatform, runPlatformOptions, { appId: this.$projectData.projectId, projectName: this.$projectData.projectName });
165+
166+
await this.$platformService.startApplication(
167+
currentPlatform,
168+
runPlatformOptions,
169+
{
170+
appId: this.$projectData.projectIdentifiers[currentPlatform.toLowerCase()],
171+
projectName: this.$projectData.projectName
172+
}
173+
);
166174
await this.$platformService.trackProjectType(this.$projectData);
167175
}
168176
}

lib/project-data.ts

+37-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as constants from "./constants";
22
import * as path from "path";
33
import { parseJson } from "./common/helpers";
44
import { EOL } from "os";
5+
import { cache } from "./common/decorators";
56

67
interface IProjectType {
78
type: string;
@@ -35,7 +36,17 @@ export class ProjectData implements IProjectData {
3536
public projectDir: string;
3637
public platformsDir: string;
3738
public projectFilePath: string;
38-
public projectId: string;
39+
public projectIdentifiers: Mobile.IProjectIdentifier;
40+
get projectId(): string {
41+
this.warnProjectId();
42+
return this.projectIdentifiers.ios;
43+
}
44+
//just in case hook/extension modifies it.
45+
set projectId(identifier: string) {
46+
this.warnProjectId();
47+
this.projectIdentifiers.ios = identifier;
48+
this.projectIdentifiers.android = identifier;
49+
}
3950
public projectName: string;
4051
public nsConfig: INsConfig;
4152
public appDirectoryPath: string;
@@ -108,7 +119,7 @@ export class ProjectData implements IProjectData {
108119
this.projectName = this.$projectHelper.sanitizeName(path.basename(projectDir));
109120
this.platformsDir = path.join(projectDir, constants.PLATFORMS_DIR_NAME);
110121
this.projectFilePath = projectFilePath;
111-
this.projectId = nsData.id;
122+
this.projectIdentifiers = this.initializeProjectIdentifiers(nsData.id);
112123
this.dependencies = packageJsonData.dependencies;
113124
this.devDependencies = packageJsonData.devDependencies;
114125
this.projectType = this.getProjectType();
@@ -206,6 +217,25 @@ export class ProjectData implements IProjectData {
206217
return path.resolve(projectDir, pathToResolve);
207218
}
208219

220+
private initializeProjectIdentifiers(data: string | Mobile.IProjectIdentifier): Mobile.IProjectIdentifier {
221+
let identifier: Mobile.IProjectIdentifier;
222+
data = data || "";
223+
224+
if (typeof data === "string") {
225+
identifier = {
226+
android: data,
227+
ios: data
228+
};
229+
} else {
230+
identifier = {
231+
android: data.android || "",
232+
ios: data.ios || ""
233+
};
234+
}
235+
236+
return identifier;
237+
}
238+
209239
private getProjectType(): string {
210240
let detectedProjectType = _.find(ProjectData.PROJECT_TYPES, (projectType) => projectType.isDefaultProjectType).type;
211241

@@ -220,5 +250,10 @@ export class ProjectData implements IProjectData {
220250

221251
return detectedProjectType;
222252
}
253+
254+
@cache()
255+
private warnProjectId(): void {
256+
this.$logger.warnWithLabel("IProjectData.projectId is deprecated. Please use IProjectData.projectIdentifiers[platform].");
257+
}
223258
}
224259
$injector.register("projectData", ProjectData);

lib/services/android-project-service.ts

+9-8
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
119119
}
120120

121121
public async validate(projectData: IProjectData): Promise<void> {
122-
this.validatePackageName(projectData.projectId);
122+
this.validatePackageName(projectData.projectIdentifiers.android);
123123
this.validateProjectName(projectData.projectName);
124124

125125
await this.$platformEnvironmentRequirements.checkEnvironmentRequirements(this.getPlatformData(projectData).normalizedPlatformName, projectData.projectDir);
@@ -258,16 +258,17 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
258258
// will replace applicationId in app/App_Resources/Android/app.gradle if it has not been edited by the user
259259
const appGradleContent = this.$fs.readText(projectData.appGradlePath);
260260
if (appGradleContent.indexOf(constants.PACKAGE_PLACEHOLDER_NAME) !== -1) {
261-
shell.sed('-i', new RegExp(constants.PACKAGE_PLACEHOLDER_NAME), projectData.projectId, projectData.appGradlePath);
261+
//TODO: For compatibility with old templates. Once all templates are updated should delete.
262+
shell.sed('-i', new RegExp(constants.PACKAGE_PLACEHOLDER_NAME), projectData.projectIdentifiers.android, projectData.appGradlePath);
262263
}
263264
} catch (e) {
264-
this.$logger.warn(`\n${e}.\nCheck if you're using an outdated template and update it.`);
265+
this.$logger.trace(`Templates updated and no need for replace in app.gradle.`);
265266
}
266267
}
267268

268269
public interpolateConfigurationFile(projectData: IProjectData, platformSpecificData: IPlatformSpecificData): void {
269270
const manifestPath = this.getPlatformData(projectData).configurationFilePath;
270-
shell.sed('-i', /__PACKAGE__/, projectData.projectId, manifestPath);
271+
shell.sed('-i', /__PACKAGE__/, projectData.projectIdentifiers.android, manifestPath);
271272
if (this.$androidToolsInfo.getToolsInfo().androidHomeEnvVar) {
272273
const sdk = (platformSpecificData && platformSpecificData.sdk) || (this.$androidToolsInfo.getToolsInfo().compileSdkVersion || "").toString();
273274
shell.sed('-i', /__APILEVEL__/, sdk, manifestPath);
@@ -276,8 +277,8 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
276277

277278
private getProjectNameFromId(projectData: IProjectData): string {
278279
let id: string;
279-
if (projectData && projectData.projectId) {
280-
const idParts = projectData.projectId.split(".");
280+
if (projectData && projectData.projectIdentifiers && projectData.projectIdentifiers.android) {
281+
const idParts = projectData.projectIdentifiers.android.split(".");
281282
id = idParts[idParts.length - 1];
282283
}
283284

@@ -519,7 +520,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
519520
const filesForInterpolation = this.$fs.enumerateFilesInDirectorySync(resourcesDestinationDirectoryPath, file => this.$fs.getFsStats(file).isDirectory() || path.extname(file) === constants.XML_FILE_EXTENSION) || [];
520521
for (const file of filesForInterpolation) {
521522
this.$logger.trace(`Interpolate data for plugin file: ${file}`);
522-
await this.$pluginVariablesService.interpolate(pluginData, file, projectData);
523+
await this.$pluginVariablesService.interpolate(pluginData, file, projectData.projectDir, projectData.projectIdentifiers.android);
523524
}
524525
}
525526

@@ -629,7 +630,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
629630

630631
public async cleanDeviceTempFolder(deviceIdentifier: string, projectData: IProjectData): Promise<void> {
631632
const adb = this.$injector.resolve(DeviceAndroidDebugBridge, { identifier: deviceIdentifier });
632-
const deviceRootPath = `${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${projectData.projectId}`;
633+
const deviceRootPath = `${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${projectData.projectIdentifiers.android}`;
633634
await adb.executeShellCommand(["rm", "-rf", deviceRootPath]);
634635
}
635636

lib/services/debug-data-service.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
export class DebugDataService implements IDebugDataService {
2+
constructor(
3+
private $devicesService: Mobile.IDevicesService
4+
) { }
25
public createDebugData(projectData: IProjectData, options: IDeviceIdentifier): IDebugData {
6+
const device = this.$devicesService.getDeviceByIdentifier(options.device);
7+
38
return {
4-
applicationIdentifier: projectData.projectId,
9+
applicationIdentifier: projectData.projectIdentifiers[device.deviceInfo.platform.toLowerCase()],
510
projectDir: projectData.projectDir,
611
deviceIdentifier: options.device,
712
projectName: projectData.projectName

lib/services/ios-project-service.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
243243
if (options && options.provision) {
244244
plistTemplate += ` <key>provisioningProfiles</key>
245245
<dict>
246-
<key>${projectData.projectId}</key>
246+
<key>${projectData.projectIdentifiers.ios}</key>
247247
<string>${options.provision}</string>
248248
</dict>`;
249249
}
@@ -292,7 +292,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
292292
if (options && options.provision) {
293293
plistTemplate += ` <key>provisioningProfiles</key>
294294
<dict>
295-
<key>${projectData.projectId}</key>
295+
<key>${projectData.projectIdentifiers.ios}</key>
296296
<string>${options.provision}</string>
297297
</dict>`;
298298
}
@@ -509,7 +509,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
509509

510510
if (shouldUpdateXcode) {
511511
const pickStart = Date.now();
512-
const mobileprovision = mobileProvisionData || await this.$iOSProvisionService.pick(provision, projectData.projectId);
512+
const mobileprovision = mobileProvisionData || await this.$iOSProvisionService.pick(provision, projectData.projectIdentifiers.ios);
513513
const pickEnd = Date.now();
514514
this.$logger.trace("Searched and " + (mobileprovision ? "found" : "failed to find ") + " matching provisioning profile. (" + (pickEnd - pickStart) + "ms.)");
515515
if (!mobileprovision) {
@@ -774,10 +774,10 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
774774
await this.$iOSEntitlementsService.merge(projectData);
775775
await this.mergeProjectXcconfigFiles(release, projectData);
776776
for (const pluginData of await this.getAllInstalledPlugins(projectData)) {
777-
await this.$pluginVariablesService.interpolatePluginVariables(pluginData, this.getPlatformData(projectData).configurationFilePath, projectData);
777+
await this.$pluginVariablesService.interpolatePluginVariables(pluginData, this.getPlatformData(projectData).configurationFilePath, projectData.projectDir);
778778
}
779779

780-
this.$pluginVariablesService.interpolateAppIdentifier(this.getPlatformData(projectData).configurationFilePath, projectData);
780+
this.$pluginVariablesService.interpolateAppIdentifier(this.getPlatformData(projectData).configurationFilePath, projectData.projectIdentifiers.ios);
781781
}
782782

783783
private getInfoPlistPath(projectData: IProjectData): string {
@@ -838,7 +838,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
838838

839839
makePatch(infoPlistPath);
840840

841-
if (projectData.projectId) {
841+
if (projectData.projectIdentifiers && projectData.projectIdentifiers.ios) {
842842
session.patch({
843843
name: "CFBundleIdentifier from package.json nativescript.id",
844844
read: () =>
@@ -847,13 +847,13 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
847847
<plist version="1.0">
848848
<dict>
849849
<key>CFBundleIdentifier</key>
850-
<string>${projectData.projectId}</string>
850+
<string>${projectData.projectIdentifiers.ios}</string>
851851
</dict>
852852
</plist>`
853853
});
854854
}
855855

856-
if (!buildOptions.release && projectData.projectId) {
856+
if (!buildOptions.release && projectData.projectIdentifiers && projectData.projectIdentifiers.ios) {
857857
session.patch({
858858
name: "CFBundleURLTypes from package.json nativescript.id",
859859
read: () =>
@@ -868,7 +868,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
868868
<string>Editor</string>
869869
<key>CFBundleURLSchemes</key>
870870
<array>
871-
<string>${projectData.projectId.replace(/[^A-Za-z0-9]/g, "")}</string>
871+
<string>${projectData.projectIdentifiers.ios.replace(/[^A-Za-z0-9]/g, "")}</string>
872872
</array>
873873
</dict>
874874
</array>

lib/services/itmstransporter-service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export class ITMSTransporterService implements IITMSTransporterService {
110110
private async getBundleIdentifier(ipaFileFullPath?: string): Promise<string> {
111111
if (!this._bundleIdentifier) {
112112
if (!ipaFileFullPath) {
113-
this._bundleIdentifier = this.$projectData.projectId;
113+
this._bundleIdentifier = this.$projectData.projectIdentifiers.ios;
114114
} else {
115115
if (!this.$fs.exists(ipaFileFullPath) || path.extname(ipaFileFullPath) !== ".ipa") {
116116
this.$errors.failWithoutHelp(`Cannot use specified ipa file ${ipaFileFullPath}. File either does not exist or is not an ipa file.`);

lib/services/livesync/android-device-livesync-sockets-service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export class AndroidDeviceSocketsLiveSyncService extends DeviceLiveSyncServiceBa
3333
this.$fs.writeFile(pathToLiveSyncFile, "");
3434
await this.device.fileSystem.putFile(pathToLiveSyncFile, this.getPathToLiveSyncFileOnDevice(deviceAppData.appIdentifier), deviceAppData.appIdentifier);
3535
await this.device.applicationManager.startApplication({ appId: deviceAppData.appIdentifier, projectName: this.data.projectName, justLaunch: true });
36-
await this.connectLivesyncTool(this.data.projectId);
36+
await this.connectLivesyncTool(this.data.projectIdentifiers.android);
3737
}
3838

3939
private getPathToLiveSyncFileOnDevice(appIdentifier: string): string {

lib/services/livesync/ios-device-livesync-service.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,18 @@ export class IOSDeviceLiveSyncService extends DeviceLiveSyncServiceBase implemen
2626
return true;
2727
}
2828

29+
const appId = projectData.projectIdentifiers.ios;
30+
2931
if (this.device.isEmulator) {
30-
await this.$iOSEmulatorServices.postDarwinNotification(this.$iOSNotification.getAttachRequest(projectData.projectId, this.device.deviceInfo.identifier), this.device.deviceInfo.identifier);
31-
const port = await this.$iOSDebuggerPortService.getPort({ projectDir: projectData.projectDir, deviceId: this.device.deviceInfo.identifier, appId: projectData.projectId });
32+
await this.$iOSEmulatorServices.postDarwinNotification(this.$iOSNotification.getAttachRequest(appId, this.device.deviceInfo.identifier), this.device.deviceInfo.identifier);
33+
const port = await this.$iOSDebuggerPortService.getPort({ projectDir: projectData.projectDir, deviceId: this.device.deviceInfo.identifier, appId });
3234
this.socket = await this.$iOSEmulatorServices.connectToPort({ port });
3335
if (!this.socket) {
3436
return false;
3537
}
3638
} else {
37-
await this.$iOSSocketRequestExecutor.executeAttachRequest(this.device, constants.AWAIT_NOTIFICATION_TIMEOUT_SECONDS, projectData.projectId);
38-
const port = await this.$iOSDebuggerPortService.getPort({ projectDir: projectData.projectDir, deviceId: this.device.deviceInfo.identifier, appId: projectData.projectId });
39+
await this.$iOSSocketRequestExecutor.executeAttachRequest(this.device, constants.AWAIT_NOTIFICATION_TIMEOUT_SECONDS, appId);
40+
const port = await this.$iOSDebuggerPortService.getPort({ projectDir: projectData.projectDir, deviceId: this.device.deviceInfo.identifier, appId });
3941
this.socket = await this.device.connectToPort(port);
4042
}
4143

0 commit comments

Comments
 (0)