diff --git a/lib/commands/debug.ts b/lib/commands/debug.ts index e0421ad2a4..33e6d7a18e 100644 --- a/lib/commands/debug.ts +++ b/lib/commands/debug.ts @@ -33,11 +33,10 @@ export class DebugPlatformCommand extends ValidatePlatformCommandBase implements const debugOptions = _.cloneDeep(this.$options.argv); - const debugData = this.$debugDataService.createDebugData(this.$projectData, this.$options); - await this.$platformService.trackProjectType(this.$projectData); const selectedDeviceForDebug = await this.getDeviceForDebug(); - debugData.deviceIdentifier = selectedDeviceForDebug.deviceInfo.identifier; + + const debugData = this.$debugDataService.createDebugData(this.$projectData, {device: selectedDeviceForDebug.deviceInfo.identifier}); if (this.$options.start) { await this.$liveSyncService.printDebugInformation(await this.$debugService.debug(debugData, debugOptions)); diff --git a/lib/common b/lib/common index a53bd014d5..a0357534d4 160000 --- a/lib/common +++ b/lib/common @@ -1 +1 @@ -Subproject commit a53bd014d553ac1203362ea3bc1fe00861cf9548 +Subproject commit a0357534d41d84da247fd2f8ccc1699335a0c41c diff --git a/lib/definitions/livesync.d.ts b/lib/definitions/livesync.d.ts index e1caed4e14..1cd3b0dc57 100644 --- a/lib/definitions/livesync.d.ts +++ b/lib/definitions/livesync.d.ts @@ -183,6 +183,16 @@ interface IHasUseHotModuleReloadOption { useHotModuleReload: boolean; } +interface ILiveSyncEventData { + deviceIdentifier: string, + applicationIdentifier?: string, + projectDir: string, + syncedFiles?: string[], + error? : Error, + notification?: string, + isFullSync?: boolean +} + interface ILatestAppPackageInstalledSettings extends IDictionary> { /* empty */ } interface IIsEmulator { diff --git a/lib/definitions/plugins.d.ts b/lib/definitions/plugins.d.ts index 6190e71356..41131b4694 100644 --- a/lib/definitions/plugins.d.ts +++ b/lib/definitions/plugins.d.ts @@ -50,40 +50,39 @@ interface IPluginVariablesService { /** * Saves plugin variables in project package.json file. * @param {IPluginData} pluginData for the plugin. - * @param {IProjectData} projectData DTO with information about the project. + * @param {string} projectDir: Specifies the directory of the project. * @return {Promise} */ - savePluginVariablesInProjectFile(pluginData: IPluginData, projectData: IProjectData): Promise; + savePluginVariablesInProjectFile(pluginData: IPluginData, projectDir: string): Promise; /** * Removes plugin variables from project package.json file. * @param {string} pluginName Name of the plugin. - * @param {IProjectData} projectData DTO with information about the project. + * @param {string} projectDir: Specifies the directory of the project. * @return {void} */ - removePluginVariablesFromProjectFile(pluginName: string, projectData: IProjectData): void; + removePluginVariablesFromProjectFile(pluginName: string, projectDir: string): void; /** * Replaces all plugin variables with their corresponding values. * @param {IPluginData} pluginData for the plugin. * @param {pluginConfigurationFilePath} pluginConfigurationFilePath for the plugin. - * @param {IProjectData} projectData DTO with information about the project. + * @param {string} projectDir: Specifies the directory of the project. * @return {Promise} */ - interpolatePluginVariables(pluginData: IPluginData, pluginConfigurationFilePath: string, projectData: IProjectData): Promise; + interpolatePluginVariables(pluginData: IPluginData, pluginConfigurationFilePath: string, projectDir: string): Promise; /** * Replaces {nativescript.id} expression with the application identifier from package.json. * @param {pluginConfigurationFilePath} pluginConfigurationFilePath for the plugin. - * @param {IProjectData} projectData DTO with information about the project. * @return {void} */ - interpolateAppIdentifier(pluginConfigurationFilePath: string, projectData: IProjectData): void; + interpolateAppIdentifier(pluginConfigurationFilePath: string, projectIdentifier: string): void; /** * Replaces both plugin variables and appIdentifier */ - interpolate(pluginData: IPluginData, pluginConfigurationFilePath: string, projectData: IProjectData): Promise; + interpolate(pluginData: IPluginData, pluginConfigurationFilePath: string, projectDir: string, projectIdentifier: string): Promise; /** * Returns the diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index 73c88f57ba..bd5c32e68c 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -77,7 +77,8 @@ interface INsConfig { interface IProjectData extends ICreateProjectData { platformsDir: string; projectFilePath: string; - projectId?: string; + projectId: string; + projectIdentifiers?: Mobile.IProjectIdentifier; dependencies: any; devDependencies: IStringDictionary; appDirectoryPath: string; diff --git a/lib/helpers/livesync-command-helper.ts b/lib/helpers/livesync-command-helper.ts index d5ab042a58..614d4606c0 100644 --- a/lib/helpers/livesync-command-helper.ts +++ b/lib/helpers/livesync-command-helper.ts @@ -167,7 +167,15 @@ export class LiveSyncCommandHelper implements ILiveSyncCommandHelper { }; await this.$platformService.deployPlatform(deployPlatformInfo); - await this.$platformService.startApplication(currentPlatform, runPlatformOptions, { appId: this.$projectData.projectId, projectName: this.$projectData.projectName }); + + await this.$platformService.startApplication( + currentPlatform, + runPlatformOptions, + { + appId: this.$projectData.projectIdentifiers[currentPlatform.toLowerCase()], + projectName: this.$projectData.projectName + } + ); await this.$platformService.trackProjectType(this.$projectData); } } diff --git a/lib/project-data.ts b/lib/project-data.ts index 90cda0cdac..7cf8bbd8c6 100644 --- a/lib/project-data.ts +++ b/lib/project-data.ts @@ -2,6 +2,7 @@ import * as constants from "./constants"; import * as path from "path"; import { parseJson } from "./common/helpers"; import { EOL } from "os"; +import { cache } from "./common/decorators"; interface IProjectType { type: string; @@ -35,7 +36,17 @@ export class ProjectData implements IProjectData { public projectDir: string; public platformsDir: string; public projectFilePath: string; - public projectId: string; + public projectIdentifiers: Mobile.IProjectIdentifier; + get projectId(): string { + this.warnProjectId(); + return this.projectIdentifiers.ios; + } + //just in case hook/extension modifies it. + set projectId(identifier: string) { + this.warnProjectId(); + this.projectIdentifiers.ios = identifier; + this.projectIdentifiers.android = identifier; + } public projectName: string; public nsConfig: INsConfig; public appDirectoryPath: string; @@ -108,7 +119,7 @@ export class ProjectData implements IProjectData { this.projectName = this.$projectHelper.sanitizeName(path.basename(projectDir)); this.platformsDir = path.join(projectDir, constants.PLATFORMS_DIR_NAME); this.projectFilePath = projectFilePath; - this.projectId = nsData.id; + this.projectIdentifiers = this.initializeProjectIdentifiers(nsData.id); this.dependencies = packageJsonData.dependencies; this.devDependencies = packageJsonData.devDependencies; this.projectType = this.getProjectType(); @@ -206,6 +217,25 @@ export class ProjectData implements IProjectData { return path.resolve(projectDir, pathToResolve); } + private initializeProjectIdentifiers(data: string | Mobile.IProjectIdentifier): Mobile.IProjectIdentifier { + let identifier: Mobile.IProjectIdentifier; + data = data || ""; + + if (typeof data === "string") { + identifier = { + android: data, + ios: data + }; + } else { + identifier = { + android: data.android || "", + ios: data.ios || "" + }; + } + + return identifier; + } + private getProjectType(): string { let detectedProjectType = _.find(ProjectData.PROJECT_TYPES, (projectType) => projectType.isDefaultProjectType).type; @@ -220,5 +250,10 @@ export class ProjectData implements IProjectData { return detectedProjectType; } + + @cache() + private warnProjectId(): void { + this.$logger.warnWithLabel("IProjectData.projectId is deprecated. Please use IProjectData.projectIdentifiers[platform]."); + } } $injector.register("projectData", ProjectData); diff --git a/lib/services/android-project-service.ts b/lib/services/android-project-service.ts index ba0fb98881..04d721ac5a 100644 --- a/lib/services/android-project-service.ts +++ b/lib/services/android-project-service.ts @@ -120,7 +120,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject } public async validate(projectData: IProjectData, options: IOptions, notConfiguredEnvOptions?: INotConfiguredEnvOptions): Promise { - this.validatePackageName(projectData.projectId); + this.validatePackageName(projectData.projectIdentifiers.android); this.validateProjectName(projectData.projectName); const checkEnvironmentRequirementsOutput = await this.$platformEnvironmentRequirements.checkEnvironmentRequirements({ @@ -269,16 +269,17 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject // will replace applicationId in app/App_Resources/Android/app.gradle if it has not been edited by the user const appGradleContent = this.$fs.readText(projectData.appGradlePath); if (appGradleContent.indexOf(constants.PACKAGE_PLACEHOLDER_NAME) !== -1) { - shell.sed('-i', new RegExp(constants.PACKAGE_PLACEHOLDER_NAME), projectData.projectId, projectData.appGradlePath); + //TODO: For compatibility with old templates. Once all templates are updated should delete. + shell.sed('-i', new RegExp(constants.PACKAGE_PLACEHOLDER_NAME), projectData.projectIdentifiers.android, projectData.appGradlePath); } } catch (e) { - this.$logger.warn(`\n${e}.\nCheck if you're using an outdated template and update it.`); + this.$logger.trace(`Templates updated and no need for replace in app.gradle.`); } } public interpolateConfigurationFile(projectData: IProjectData, platformSpecificData: IPlatformSpecificData): void { const manifestPath = this.getPlatformData(projectData).configurationFilePath; - shell.sed('-i', /__PACKAGE__/, projectData.projectId, manifestPath); + shell.sed('-i', /__PACKAGE__/, projectData.projectIdentifiers.android, manifestPath); if (this.$androidToolsInfo.getToolsInfo().androidHomeEnvVar) { const sdk = (platformSpecificData && platformSpecificData.sdk) || (this.$androidToolsInfo.getToolsInfo().compileSdkVersion || "").toString(); shell.sed('-i', /__APILEVEL__/, sdk, manifestPath); @@ -287,8 +288,8 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject private getProjectNameFromId(projectData: IProjectData): string { let id: string; - if (projectData && projectData.projectId) { - const idParts = projectData.projectId.split("."); + if (projectData && projectData.projectIdentifiers && projectData.projectIdentifiers.android) { + const idParts = projectData.projectIdentifiers.android.split("."); id = idParts[idParts.length - 1]; } @@ -532,7 +533,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject const filesForInterpolation = this.$fs.enumerateFilesInDirectorySync(resourcesDestinationDirectoryPath, file => this.$fs.getFsStats(file).isDirectory() || path.extname(file) === constants.XML_FILE_EXTENSION) || []; for (const file of filesForInterpolation) { this.$logger.trace(`Interpolate data for plugin file: ${file}`); - await this.$pluginVariablesService.interpolate(pluginData, file, projectData); + await this.$pluginVariablesService.interpolate(pluginData, file, projectData.projectDir, projectData.projectIdentifiers.android); } } @@ -642,7 +643,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject public async cleanDeviceTempFolder(deviceIdentifier: string, projectData: IProjectData): Promise { const adb = this.$injector.resolve(DeviceAndroidDebugBridge, { identifier: deviceIdentifier }); - const deviceRootPath = `${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${projectData.projectId}`; + const deviceRootPath = `${LiveSyncPaths.ANDROID_TMP_DIR_NAME}/${projectData.projectIdentifiers.android}`; await adb.executeShellCommand(["rm", "-rf", deviceRootPath]); } diff --git a/lib/services/debug-data-service.ts b/lib/services/debug-data-service.ts index 3584f2165f..77ae6705f8 100644 --- a/lib/services/debug-data-service.ts +++ b/lib/services/debug-data-service.ts @@ -1,7 +1,12 @@ export class DebugDataService implements IDebugDataService { + constructor( + private $devicesService: Mobile.IDevicesService + ) { } public createDebugData(projectData: IProjectData, options: IDeviceIdentifier): IDebugData { + const device = this.$devicesService.getDeviceByIdentifier(options.device); + return { - applicationIdentifier: projectData.projectId, + applicationIdentifier: projectData.projectIdentifiers[device.deviceInfo.platform.toLowerCase()], projectDir: projectData.projectDir, deviceIdentifier: options.device, projectName: projectData.projectName diff --git a/lib/services/ios-project-service.ts b/lib/services/ios-project-service.ts index a955e27ec8..109db3c309 100644 --- a/lib/services/ios-project-service.ts +++ b/lib/services/ios-project-service.ts @@ -246,7 +246,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ if (options && options.provision) { plistTemplate += ` provisioningProfiles - ${projectData.projectId} + ${projectData.projectIdentifiers.ios} ${options.provision} `; } @@ -295,7 +295,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ if (options && options.provision) { plistTemplate += ` provisioningProfiles - ${projectData.projectId} + ${projectData.projectIdentifiers.ios} ${options.provision} `; } @@ -512,7 +512,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ if (shouldUpdateXcode) { const pickStart = Date.now(); - const mobileprovision = mobileProvisionData || await this.$iOSProvisionService.pick(provision, projectData.projectId); + const mobileprovision = mobileProvisionData || await this.$iOSProvisionService.pick(provision, projectData.projectIdentifiers.ios); const pickEnd = Date.now(); this.$logger.trace("Searched and " + (mobileprovision ? "found" : "failed to find ") + " matching provisioning profile. (" + (pickEnd - pickStart) + "ms.)"); if (!mobileprovision) { @@ -777,10 +777,10 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f await this.$iOSEntitlementsService.merge(projectData); await this.mergeProjectXcconfigFiles(release, projectData); for (const pluginData of await this.getAllInstalledPlugins(projectData)) { - await this.$pluginVariablesService.interpolatePluginVariables(pluginData, this.getPlatformData(projectData).configurationFilePath, projectData); + await this.$pluginVariablesService.interpolatePluginVariables(pluginData, this.getPlatformData(projectData).configurationFilePath, projectData.projectDir); } - this.$pluginVariablesService.interpolateAppIdentifier(this.getPlatformData(projectData).configurationFilePath, projectData); + this.$pluginVariablesService.interpolateAppIdentifier(this.getPlatformData(projectData).configurationFilePath, projectData.projectIdentifiers.ios); } private getInfoPlistPath(projectData: IProjectData): string { @@ -841,7 +841,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f makePatch(infoPlistPath); - if (projectData.projectId) { + if (projectData.projectIdentifiers && projectData.projectIdentifiers.ios) { session.patch({ name: "CFBundleIdentifier from package.json nativescript.id", read: () => @@ -850,13 +850,13 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f CFBundleIdentifier - ${projectData.projectId} + ${projectData.projectIdentifiers.ios} ` }); } - if (!buildOptions.release && projectData.projectId) { + if (!buildOptions.release && projectData.projectIdentifiers && projectData.projectIdentifiers.ios) { session.patch({ name: "CFBundleURLTypes from package.json nativescript.id", read: () => @@ -871,7 +871,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f Editor CFBundleURLSchemes - ${projectData.projectId.replace(/[^A-Za-z0-9]/g, "")} + ${projectData.projectIdentifiers.ios.replace(/[^A-Za-z0-9]/g, "")} diff --git a/lib/services/itmstransporter-service.ts b/lib/services/itmstransporter-service.ts index 474aea69c0..1536c4d1d8 100644 --- a/lib/services/itmstransporter-service.ts +++ b/lib/services/itmstransporter-service.ts @@ -110,7 +110,7 @@ export class ITMSTransporterService implements IITMSTransporterService { private async getBundleIdentifier(ipaFileFullPath?: string): Promise { if (!this._bundleIdentifier) { if (!ipaFileFullPath) { - this._bundleIdentifier = this.$projectData.projectId; + this._bundleIdentifier = this.$projectData.projectIdentifiers.ios; } else { if (!this.$fs.exists(ipaFileFullPath) || path.extname(ipaFileFullPath) !== ".ipa") { this.$errors.failWithoutHelp(`Cannot use specified ipa file ${ipaFileFullPath}. File either does not exist or is not an ipa file.`); diff --git a/lib/services/livesync/android-device-livesync-sockets-service.ts b/lib/services/livesync/android-device-livesync-sockets-service.ts index 9925588c86..632d5f3ecc 100644 --- a/lib/services/livesync/android-device-livesync-sockets-service.ts +++ b/lib/services/livesync/android-device-livesync-sockets-service.ts @@ -32,7 +32,7 @@ export class AndroidDeviceSocketsLiveSyncService extends AndroidDeviceLiveSyncSe this.$fs.writeFile(pathToLiveSyncFile, ""); await this.device.fileSystem.putFile(pathToLiveSyncFile, this.getPathToLiveSyncFileOnDevice(deviceAppData.appIdentifier), deviceAppData.appIdentifier); await this.device.applicationManager.startApplication({ appId: deviceAppData.appIdentifier, projectName: this.data.projectName, justLaunch: true }); - await this.connectLivesyncTool(this.data.projectId); + await this.connectLivesyncTool(this.data.projectIdentifiers.android); } private getPathToLiveSyncFileOnDevice(appIdentifier: string): string { diff --git a/lib/services/livesync/ios-device-livesync-service.ts b/lib/services/livesync/ios-device-livesync-service.ts index d546ab14f4..5e7fb8ffce 100644 --- a/lib/services/livesync/ios-device-livesync-service.ts +++ b/lib/services/livesync/ios-device-livesync-service.ts @@ -26,16 +26,18 @@ export class IOSDeviceLiveSyncService extends DeviceLiveSyncServiceBase implemen return true; } + const appId = projectData.projectIdentifiers.ios; + if (this.device.isEmulator) { - await this.$iOSEmulatorServices.postDarwinNotification(this.$iOSNotification.getAttachRequest(projectData.projectId, this.device.deviceInfo.identifier), this.device.deviceInfo.identifier); - const port = await this.$iOSDebuggerPortService.getPort({ projectDir: projectData.projectDir, deviceId: this.device.deviceInfo.identifier, appId: projectData.projectId }); + await this.$iOSEmulatorServices.postDarwinNotification(this.$iOSNotification.getAttachRequest(appId, this.device.deviceInfo.identifier), this.device.deviceInfo.identifier); + const port = await this.$iOSDebuggerPortService.getPort({ projectDir: projectData.projectDir, deviceId: this.device.deviceInfo.identifier, appId }); this.socket = await this.$iOSEmulatorServices.connectToPort({ port }); if (!this.socket) { return false; } } else { - await this.$iOSSocketRequestExecutor.executeAttachRequest(this.device, constants.AWAIT_NOTIFICATION_TIMEOUT_SECONDS, projectData.projectId); - const port = await this.$iOSDebuggerPortService.getPort({ projectDir: projectData.projectDir, deviceId: this.device.deviceInfo.identifier, appId: projectData.projectId }); + await this.$iOSSocketRequestExecutor.executeAttachRequest(this.device, constants.AWAIT_NOTIFICATION_TIMEOUT_SECONDS, appId); + const port = await this.$iOSDebuggerPortService.getPort({ projectDir: projectData.projectDir, deviceId: this.device.deviceInfo.identifier, appId }); this.socket = await this.device.connectToPort(port); } diff --git a/lib/services/livesync/livesync-service.ts b/lib/services/livesync/livesync-service.ts index 1d908a991b..a8c2068fba 100644 --- a/lib/services/livesync/livesync-service.ts +++ b/lib/services/livesync/livesync-service.ts @@ -100,7 +100,7 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi // Emit LiveSync stopped when we've really stopped. _.each(removedDeviceIdentifiers, deviceIdentifier => { - this.emit(LiveSyncEvents.liveSyncStopped, { projectDir, deviceIdentifier }); + this.emitLivesyncEvent(LiveSyncEvents.liveSyncStopped, { projectDir, deviceIdentifier }); }); } } @@ -120,26 +120,28 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi } private async refreshApplicationWithoutDebug(projectData: IProjectData, liveSyncResultInfo: ILiveSyncResultInfo, debugOpts?: IDebugOptions, outputPath?: string, settings?: IShouldSkipEmitLiveSyncNotification): Promise { - const platformLiveSyncService = this.getLiveSyncService(liveSyncResultInfo.deviceAppData.platform); + const platform = liveSyncResultInfo.deviceAppData.platform; + const platformLiveSyncService = this.getLiveSyncService(platform); + const applicationIdentifier = projectData.projectIdentifiers[platform.toLowerCase()]; try { await platformLiveSyncService.refreshApplication(projectData, liveSyncResultInfo); } catch (err) { - this.$logger.info(`Error while trying to start application ${projectData.projectId} on device ${liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier}. Error is: ${err.message || err}`); - const msg = `Unable to start application ${projectData.projectId} on device ${liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier}. Try starting it manually.`; + this.$logger.info(`Error while trying to start application ${applicationIdentifier} on device ${liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier}. Error is: ${err.message || err}`); + const msg = `Unable to start application ${applicationIdentifier} on device ${liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier}. Try starting it manually.`; this.$logger.warn(msg); if (!settings || !settings.shouldSkipEmitLiveSyncNotification) { - this.emit(LiveSyncEvents.liveSyncNotification, { + this.emitLivesyncEvent(LiveSyncEvents.liveSyncNotification, { projectDir: projectData.projectDir, - applicationIdentifier: projectData.projectId, + applicationIdentifier, deviceIdentifier: liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier, notification: msg }); } } - this.emit(LiveSyncEvents.liveSyncExecuted, { + this.emitLivesyncEvent(LiveSyncEvents.liveSyncExecuted, { projectDir: projectData.projectDir, - applicationIdentifier: projectData.projectId, + applicationIdentifier, syncedFiles: liveSyncResultInfo.modifiedFilesData.map(m => m.getLocalPath()), deviceIdentifier: liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier, isFullSync: liveSyncResultInfo.isFullSync @@ -483,9 +485,10 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi const settings = this.getDefaultLatestAppPackageInstalledSettings(); // Now fullSync const deviceAction = async (device: Mobile.IDevice): Promise => { + const platform = device.deviceInfo.platform; try { - const platform = device.deviceInfo.platform; const platformLiveSyncService = this.getLiveSyncService(platform); + const deviceBuildInfoDescriptor = _.find(deviceDescriptors, dd => dd.identifier === device.deviceInfo.identifier); await this.ensureLatestAppPackageIsInstalledOnDevice({ @@ -516,19 +519,19 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi await this.$platformService.trackActionForPlatform({ action: "LiveSync", platform: device.deviceInfo.platform, isForDevice: !device.isEmulator, deviceOsVersion: device.deviceInfo.version }); await this.refreshApplication(projectData, liveSyncResultInfo, deviceBuildInfoDescriptor.debugOptions, deviceBuildInfoDescriptor.outputPath); - this.emit(LiveSyncEvents.liveSyncStarted, { + this.emitLivesyncEvent(LiveSyncEvents.liveSyncStarted, { projectDir: projectData.projectDir, deviceIdentifier: device.deviceInfo.identifier, - applicationIdentifier: projectData.projectId + applicationIdentifier: projectData.projectIdentifiers[platform.toLowerCase()] }); } catch (err) { this.$logger.warn(`Unable to apply changes on device: ${device.deviceInfo.identifier}. Error is: ${err.message}.`); - this.emit(LiveSyncEvents.liveSyncError, { + this.emitLivesyncEvent(LiveSyncEvents.liveSyncError, { error: err, deviceIdentifier: device.deviceInfo.identifier, projectDir: projectData.projectDir, - applicationIdentifier: projectData.projectId + applicationIdentifier: projectData.projectIdentifiers[platform.toLowerCase()] }); await this.stopLiveSync(projectData.projectDir, [device.deviceInfo.identifier], { shouldAwaitAllActions: false }); @@ -666,12 +669,12 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi if (allErrors && _.isArray(allErrors)) { for (const deviceError of allErrors) { this.$logger.warn(`Unable to apply changes for device: ${deviceError.deviceIdentifier}. Error is: ${deviceError.message}.`); - - this.emit(LiveSyncEvents.liveSyncError, { + const device = this.$devicesService.getDeviceByIdentifier(deviceError.deviceIdentifier); + this.emitLivesyncEvent(LiveSyncEvents.liveSyncError, { error: deviceError, deviceIdentifier: deviceError.deviceIdentifier, projectDir: projectData.projectDir, - applicationIdentifier: projectData.projectId + applicationIdentifier: projectData.projectIdentifiers[device.deviceInfo.platform.toLowerCase()] }); await this.stopLiveSync(projectData.projectDir, [deviceError.deviceIdentifier], { shouldAwaitAllActions: false }); @@ -790,6 +793,11 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi } } + public emitLivesyncEvent (event: string, livesyncData: ILiveSyncEventData): boolean { + this.$logger.trace(`Will emit event ${event} with data`, livesyncData); + return this.emit(event, livesyncData); + } + } $injector.register("liveSyncService", LiveSyncService); diff --git a/lib/services/livesync/platform-livesync-service-base.ts b/lib/services/livesync/platform-livesync-service-base.ts index 3189ae813d..1b5d0e225d 100644 --- a/lib/services/livesync/platform-livesync-service-base.ts +++ b/lib/services/livesync/platform-livesync-service-base.ts @@ -14,9 +14,10 @@ export abstract class PlatformLiveSyncServiceBase { private $projectFilesProvider: IProjectFilesProvider) { } public getDeviceLiveSyncService(device: Mobile.IDevice, projectData: IProjectData): INativeScriptDeviceLiveSyncService { + const platform = device.deviceInfo.platform.toLowerCase(); const platformData = this.$platformsData.getPlatformData(device.deviceInfo.platform, projectData); const frameworkVersion = platformData.platformProjectService.getFrameworkVersion(projectData); - const key = getHash(`${device.deviceInfo.identifier}${projectData.projectId}${projectData.projectDir}${frameworkVersion}`); + const key = getHash(`${device.deviceInfo.identifier}${projectData.projectIdentifiers[platform]}${projectData.projectDir}${frameworkVersion}`); if (!this._deviceLiveSyncServicesCache[key]) { this._deviceLiveSyncServicesCache[key] = this._getDeviceLiveSyncService(device, projectData, frameworkVersion); } @@ -125,9 +126,11 @@ export abstract class PlatformLiveSyncServiceBase { } protected async getAppData(syncInfo: IFullSyncInfo): Promise { - const deviceProjectRootOptions: IDeviceProjectRootOptions = _.assign({ appIdentifier: syncInfo.projectData.projectId }, syncInfo); + const platform = syncInfo.device.deviceInfo.platform.toLowerCase(); + const appIdentifier = syncInfo.projectData.projectIdentifiers[platform]; + const deviceProjectRootOptions: IDeviceProjectRootOptions = _.assign({ appIdentifier }, syncInfo); return { - appIdentifier: syncInfo.projectData.projectId, + appIdentifier, device: syncInfo.device, platform: syncInfo.device.deviceInfo.platform, getDeviceProjectRootPath: () => this.$devicePathProvider.getDeviceProjectRootPath(syncInfo.device, deviceProjectRootOptions), diff --git a/lib/services/platform-service.ts b/lib/services/platform-service.ts index dcef7a3240..a1b43b659a 100644 --- a/lib/services/platform-service.ts +++ b/lib/services/platform-service.ts @@ -97,7 +97,7 @@ export class PlatformService extends EventEmitter implements IPlatformService { // Log the values for project this.$logger.trace("Creating NativeScript project for the %s platform", platform); this.$logger.trace("Path: %s", platformData.projectRoot); - this.$logger.trace("Package: %s", projectData.projectId); + this.$logger.trace("Package: %s", projectData.projectIdentifiers[platform]); this.$logger.trace("Name: %s", projectData.projectName); this.$logger.out("Copying template files..."); @@ -260,14 +260,24 @@ export class PlatformService extends EventEmitter implements IPlatformService { platform = this.$mobileHelper.normalizePlatformName(platform); this.$logger.trace("Validate options for platform: " + platform); const platformData = this.$platformsData.getPlatformData(platform, projectData); - const result = await platformData.platformProjectService.validateOptions(projectData.projectId, provision, teamId); + + const result = await platformData.platformProjectService.validateOptions( + projectData.projectIdentifiers[platform.toLowerCase()], + provision, + teamId + ); + return result; } else { let valid = true; for (const availablePlatform in this.$platformsData.availablePlatforms) { this.$logger.trace("Validate options for platform: " + availablePlatform); const platformData = this.$platformsData.getPlatformData(availablePlatform, projectData); - valid = valid && await platformData.platformProjectService.validateOptions(projectData.projectId, provision, teamId); + valid = valid && await platformData.platformProjectService.validateOptions( + projectData.projectIdentifiers[availablePlatform.toLowerCase()], + provision, + teamId + ); } return valid; @@ -459,7 +469,7 @@ export class PlatformService extends EventEmitter implements IPlatformService { public async shouldInstall(device: Mobile.IDevice, projectData: IProjectData, release: IBuildConfig, outputPath?: string): Promise { const platform = device.deviceInfo.platform; - if (!(await device.applicationManager.isApplicationInstalled(projectData.projectId))) { + if (!(await device.applicationManager.isApplicationInstalled(projectData.projectIdentifiers[platform.toLowerCase()]))) { return true; } @@ -489,11 +499,12 @@ export class PlatformService extends EventEmitter implements IPlatformService { await platformData.platformProjectService.cleanDeviceTempFolder(device.deviceInfo.identifier, projectData); - await device.applicationManager.reinstallApplication(projectData.projectId, packageFile); + const platform = device.deviceInfo.platform.toLowerCase(); + await device.applicationManager.reinstallApplication(projectData.projectIdentifiers[platform], packageFile); await this.updateHashesOnDevice({ device, - appIdentifier: projectData.projectId, + appIdentifier: projectData.projectIdentifiers[platform], outputFilePath, platformData }); @@ -503,7 +514,7 @@ export class PlatformService extends EventEmitter implements IPlatformService { const options = buildConfig; options.buildForDevice = !device.isEmulator; const buildInfoFilePath = outputFilePath || this.getBuildOutputPath(device.deviceInfo.platform, platformData, options); - const appIdentifier = projectData.projectId; + const appIdentifier = projectData.projectIdentifiers[platform]; await device.fileSystem.putFile(path.join(buildInfoFilePath, buildInfoFileName), deviceFilePath, appIdentifier); } @@ -608,8 +619,9 @@ export class PlatformService extends EventEmitter implements IPlatformService { } private async getDeviceBuildInfoFilePath(device: Mobile.IDevice, projectData: IProjectData): Promise { + const platform = device.deviceInfo.platform.toLowerCase(); const deviceRootPath = await this.$devicePathProvider.getDeviceProjectRootPath(device, { - appIdentifier: projectData.projectId, + appIdentifier: projectData.projectIdentifiers[platform], getDirname: true }); return helpers.fromWindowsRelativePathToUnix(path.join(deviceRootPath, buildInfoFileName)); @@ -918,8 +930,9 @@ export class PlatformService extends EventEmitter implements IPlatformService { public async readFile(device: Mobile.IDevice, deviceFilePath: string, projectData: IProjectData): Promise { temp.track(); const uniqueFilePath = temp.path({ suffix: ".tmp" }); + const platform = device.deviceInfo.platform.toLowerCase(); try { - await device.fileSystem.getFile(deviceFilePath, projectData.projectId, uniqueFilePath); + await device.fileSystem.getFile(deviceFilePath, projectData.projectIdentifiers[platform], uniqueFilePath); } catch (e) { return null; } diff --git a/lib/services/plugin-variables-service.ts b/lib/services/plugin-variables-service.ts index ccb822fcc5..d73ed0a56d 100644 --- a/lib/services/plugin-variables-service.ts +++ b/lib/services/plugin-variables-service.ts @@ -13,42 +13,42 @@ export class PluginVariablesService implements IPluginVariablesService { return `${pluginName}-${PluginVariablesService.PLUGIN_VARIABLES_KEY}`; } - public async savePluginVariablesInProjectFile(pluginData: IPluginData, projectData: IProjectData): Promise { + public async savePluginVariablesInProjectFile(pluginData: IPluginData, projectDir: string): Promise { const values = Object.create(null); await this.executeForAllPluginVariables(pluginData, async (pluginVariableData: IPluginVariableData) => { const pluginVariableValue = await this.getPluginVariableValue(pluginVariableData); this.ensurePluginVariableValue(pluginVariableValue, `Unable to find value for ${pluginVariableData.name} plugin variable from ${pluginData.name} plugin. Ensure the --var option is specified or the plugin variable has default value.`); values[pluginVariableData.name] = pluginVariableValue; - }, projectData); + }, projectDir); if (!_.isEmpty(values)) { - this.$projectDataService.setNSValue(projectData.projectDir, this.getPluginVariablePropertyName(pluginData.name), values); + this.$projectDataService.setNSValue(projectDir, this.getPluginVariablePropertyName(pluginData.name), values); } } - public removePluginVariablesFromProjectFile(pluginName: string, projectData: IProjectData): void { - this.$projectDataService.removeNSProperty(projectData.projectDir, this.getPluginVariablePropertyName(pluginName)); + public removePluginVariablesFromProjectFile(pluginName: string, projectDir: string): void { + this.$projectDataService.removeNSProperty(projectDir, this.getPluginVariablePropertyName(pluginName)); } - public async interpolatePluginVariables(pluginData: IPluginData, pluginConfigurationFilePath: string, projectData: IProjectData): Promise { + public async interpolatePluginVariables(pluginData: IPluginData, pluginConfigurationFilePath: string, projectDir: string): Promise { let pluginConfigurationFileContent = this.$fs.readText(pluginConfigurationFilePath); await this.executeForAllPluginVariables(pluginData, async (pluginVariableData: IPluginVariableData) => { this.ensurePluginVariableValue(pluginVariableData.value, `Unable to find the value for ${pluginVariableData.name} plugin variable into project package.json file. Verify that your package.json file is correct and try again.`); pluginConfigurationFileContent = this.interpolateCore(pluginVariableData.name, pluginVariableData.value, pluginConfigurationFileContent); - }, projectData); + }, projectDir); this.$fs.writeFile(pluginConfigurationFilePath, pluginConfigurationFileContent); } - public interpolateAppIdentifier(pluginConfigurationFilePath: string, projectData: IProjectData): void { + public interpolateAppIdentifier(pluginConfigurationFilePath: string, projectIdentifier: string): void { const pluginConfigurationFileContent = this.$fs.readText(pluginConfigurationFilePath); - const newContent = this.interpolateCore("nativescript.id", projectData.projectId, pluginConfigurationFileContent); + const newContent = this.interpolateCore("nativescript.id", projectIdentifier, pluginConfigurationFileContent); this.$fs.writeFile(pluginConfigurationFilePath, newContent); } - public async interpolate(pluginData: IPluginData, pluginConfigurationFilePath: string, projectData: IProjectData): Promise { - await this.interpolatePluginVariables(pluginData, pluginConfigurationFilePath, projectData); - this.interpolateAppIdentifier(pluginConfigurationFilePath, projectData); + public async interpolate(pluginData: IPluginData, pluginConfigurationFilePath: string, projectDir: string, projectIdentifier: string): Promise { + await this.interpolatePluginVariables(pluginData, pluginConfigurationFilePath, projectDir); + this.interpolateAppIdentifier(pluginConfigurationFilePath, projectIdentifier); } private interpolateCore(name: string, value: string, content: string): string { @@ -83,18 +83,18 @@ export class PluginVariablesService implements IPluginVariablesService { return value; } - private async executeForAllPluginVariables(pluginData: IPluginData, action: (pluginVariableData: IPluginVariableData) => Promise, projectData: IProjectData): Promise { + private async executeForAllPluginVariables(pluginData: IPluginData, action: (pluginVariableData: IPluginVariableData) => Promise, projectDir: string): Promise { const pluginVariables = pluginData.pluginVariables; const pluginVariablesNames = _.keys(pluginVariables); - await Promise.all(_.map(pluginVariablesNames, pluginVariableName => action(this.createPluginVariableData(pluginData, pluginVariableName, projectData)))); + await Promise.all(_.map(pluginVariablesNames, pluginVariableName => action(this.createPluginVariableData(pluginData, pluginVariableName, projectDir)))); } - private createPluginVariableData(pluginData: IPluginData, pluginVariableName: string, projectData: IProjectData): IPluginVariableData { + private createPluginVariableData(pluginData: IPluginData, pluginVariableName: string, projectDir: string): IPluginVariableData { const variableData = pluginData.pluginVariables[pluginVariableName]; variableData.name = pluginVariableName; - const pluginVariableValues = this.$projectDataService.getNSValue(projectData.projectDir, this.getPluginVariablePropertyName(pluginData.name)); + const pluginVariableValues = this.$projectDataService.getNSValue(projectDir, this.getPluginVariablePropertyName(pluginData.name)); variableData.value = pluginVariableValues ? pluginVariableValues[pluginVariableName] : undefined; return variableData; diff --git a/lib/services/plugins-service.ts b/lib/services/plugins-service.ts index a3ca25297e..8e57801eea 100644 --- a/lib/services/plugins-service.ts +++ b/lib/services/plugins-service.ts @@ -62,7 +62,7 @@ export class PluginsService implements IPluginsService { await this.executeForAllInstalledPlatforms(action, projectData); try { - await this.$pluginVariablesService.savePluginVariablesInProjectFile(pluginData, projectData); + await this.$pluginVariablesService.savePluginVariablesInProjectFile(pluginData, projectData.projectDir); } catch (err) { // Revert package.json this.$projectDataService.removeNSProperty(projectData.projectDir, this.$pluginVariablesService.getPluginVariablePropertyName(pluginData.name)); @@ -85,7 +85,7 @@ export class PluginsService implements IPluginsService { await platformData.platformProjectService.removePluginNativeCode(pluginData, projectData); }; - this.$pluginVariablesService.removePluginVariablesFromProjectFile(pluginName.toLowerCase(), projectData); + this.$pluginVariablesService.removePluginVariablesFromProjectFile(pluginName.toLowerCase(), projectData.projectDir); await this.executeForAllInstalledPlatforms(removePluginNativeCodeAction, projectData); await this.executeNpmCommand(PluginsService.UNINSTALL_COMMAND_NAME, pluginName, projectData); diff --git a/lib/services/project-service.ts b/lib/services/project-service.ts index a71156ee1d..4e44481dee 100644 --- a/lib/services/project-service.ts +++ b/lib/services/project-service.ts @@ -103,7 +103,7 @@ export class ProjectService implements IProjectService { try { const projectData = this.$projectDataService.getProjectData(pathToProject); - return !!projectData && !!projectData.projectDir && !!projectData.projectId; + return !!projectData && !!projectData.projectDir && !!(projectData.projectIdentifiers.ios && projectData.projectIdentifiers.android); } catch (e) { return false; } diff --git a/test/ios-project-service.ts b/test/ios-project-service.ts index b123541039..1d538e3439 100644 --- a/test/ios-project-service.ts +++ b/test/ios-project-service.ts @@ -69,7 +69,9 @@ function createTestInjector(projectPath: string, projectName: string, xcode?: IX platformsDir: path.join(projectPath, "platforms"), projectName: projectName, projectPath: projectPath, - projectFilePath: path.join(projectPath, "package.json") + projectFilePath: path.join(projectPath, "package.json"), + projectId: "", + projectIdentifiers: { android: "", ios: ""} }); testInjector.register("projectData", projectData); testInjector.register("projectHelper", {}); diff --git a/test/platform-service.ts b/test/platform-service.ts index d025c66f29..d7b9eb0aab 100644 --- a/test/platform-service.ts +++ b/test/platform-service.ts @@ -191,6 +191,7 @@ describe('Platform Service Tests', () => { beforeEach(() => { testInjector = createTestInjector(); testInjector.register("fs", stubs.FileSystemStub); + testInjector.resolve("projectData").initializeProjectData(); platformService = testInjector.resolve("platformService"); }); @@ -389,6 +390,7 @@ describe('Platform Service Tests', () => { testInjector = createTestInjector(); testInjector.register("fs", fsLib.FileSystem); fs = testInjector.resolve("fs"); + testInjector.resolve("projectData").initializeProjectData(); }); function prepareDirStructure() { diff --git a/test/plugin-variables-service.ts b/test/plugin-variables-service.ts index c99f24cb11..86657459e3 100644 --- a/test/plugin-variables-service.ts +++ b/test/plugin-variables-service.ts @@ -56,7 +56,9 @@ async function createProjectFile(testInjector: IInjector): Promise { const projectData = { "name": "myProject", - "nativescript": {} + "nativescript": { + id: { android: "", ios: ""} + } }; testInjector.resolve("fs").writeJson(path.join(tempFolder, "package.json"), projectData); @@ -105,7 +107,7 @@ describe("Plugin Variables service", () => { let actualError: string = null; try { - await pluginVariablesService.savePluginVariablesInProjectFile(pluginData, projectData); + await pluginVariablesService.savePluginVariablesInProjectFile(pluginData, projectData.projectDir); } catch (err) { actualError = err.message; } @@ -125,7 +127,7 @@ describe("Plugin Variables service", () => { const pluginVariablesService: IPluginVariablesService = testInjector.resolve("pluginVariablesService"); const projectData: IProjectData = testInjector.resolve("projectData"); projectData.initializeProjectData(); - await pluginVariablesService.savePluginVariablesInProjectFile(pluginData, projectData); + await pluginVariablesService.savePluginVariablesInProjectFile(pluginData, projectData.projectDir); const fs = testInjector.resolve("fs"); const staticConfig: IStaticConfig = testInjector.resolve("staticConfig"); @@ -143,7 +145,7 @@ describe("Plugin Variables service", () => { const projectData = testInjector.resolve("projectData"); projectData.initializeProjectData(); - await pluginVariablesService.savePluginVariablesInProjectFile(pluginData, projectData); + await pluginVariablesService.savePluginVariablesInProjectFile(pluginData, projectData.projectDir); const fs = testInjector.resolve("fs"); const staticConfig: IStaticConfig = testInjector.resolve("staticConfig"); @@ -170,7 +172,7 @@ describe("Plugin Variables service", () => { const pluginVariablesService: IPluginVariablesService = testInjector.resolve("pluginVariablesService"); const projectData = testInjector.resolve("projectData"); projectData.initializeProjectData(); - await pluginVariablesService.savePluginVariablesInProjectFile(pluginData, projectData); + await pluginVariablesService.savePluginVariablesInProjectFile(pluginData, projectData.projectDir); const fs = testInjector.resolve("fs"); const staticConfig: IStaticConfig = testInjector.resolve("staticConfig"); @@ -188,7 +190,7 @@ describe("Plugin Variables service", () => { const projectData = testInjector.resolve("projectData"); projectData.initializeProjectData(); - await pluginVariablesService.savePluginVariablesInProjectFile(pluginData, projectData); + await pluginVariablesService.savePluginVariablesInProjectFile(pluginData, projectData.projectDir); const fs = testInjector.resolve("fs"); const staticConfig: IStaticConfig = testInjector.resolve("staticConfig"); @@ -209,7 +211,7 @@ describe("Plugin Variables service", () => { const pluginVariablesService: IPluginVariablesService = testInjector.resolve("pluginVariablesService"); const projectData = testInjector.resolve("projectData"); projectData.initializeProjectData(); - await pluginVariablesService.savePluginVariablesInProjectFile(pluginData, projectData); + await pluginVariablesService.savePluginVariablesInProjectFile(pluginData, projectData.projectDir); const fs = testInjector.resolve("fs"); const staticConfig: IStaticConfig = testInjector.resolve("staticConfig"); @@ -237,7 +239,7 @@ describe("Plugin Variables service", () => { const expectedError = "Unable to find the value for MY_VAR plugin variable into project package.json file. Verify that your package.json file is correct and try again."; let error: string = null; try { - await pluginVariablesService.interpolatePluginVariables(pluginData, filePath, projectData); + await pluginVariablesService.interpolatePluginVariables(pluginData, filePath, projectData.projectDir); } catch (err) { error = err.message; } @@ -272,7 +274,7 @@ describe("Plugin Variables service", () => { const filePath = path.join(tempFolder, "myfile"); fs.writeFile(filePath, pluginConfigurationFileContent); - await pluginVariablesService.interpolatePluginVariables(pluginData, filePath, projectData); + await pluginVariablesService.interpolatePluginVariables(pluginData, filePath, projectData.projectDir); const result = fs.readText(filePath); const expectedResult = '' + @@ -312,7 +314,7 @@ describe("Plugin Variables service", () => { const filePath = path.join(tempFolder, "myfile"); fs.writeFile(filePath, pluginConfigurationFileContent); - await pluginVariablesService.interpolatePluginVariables(pluginData, filePath, projectData); + await pluginVariablesService.interpolatePluginVariables(pluginData, filePath, projectData.projectDir); const result = fs.readText(filePath); const expectedResult = '' + @@ -353,7 +355,7 @@ describe("Plugin Variables service", () => { const filePath = path.join(tempFolder, "myfile"); fs.writeFile(filePath, pluginConfigurationFileContent); - await pluginVariablesService.interpolatePluginVariables(pluginData, filePath, projectData); + await pluginVariablesService.interpolatePluginVariables(pluginData, filePath, projectData.projectDir); const result = fs.readText(filePath); const expectedResult = '' + diff --git a/test/project-data.ts b/test/project-data.ts index 5a465b6611..956a107efa 100644 --- a/test/project-data.ts +++ b/test/project-data.ts @@ -50,7 +50,9 @@ describe("projectData", () => { fs.exists = (filePath: string) => filePath && path.basename(filePath) === "package.json"; fs.readText = () => (JSON.stringify({ - nativescript: {}, + nativescript: { + id: "com.test.testid" + }, dependencies: dependencies, devDependencies: devDependencies })); diff --git a/test/project-service.ts b/test/project-service.ts index 2e887c6eb0..833c03da2a 100644 --- a/test/project-service.ts +++ b/test/project-service.ts @@ -446,7 +446,8 @@ describe("Project Service Tests", () => { it("returns true when getProjectData does not throw, projectDir and projectId are valid", () => { const testInjector = getTestInjector({ projectDir: "projectDir", - projectId: "projectId" + projectId: "projectId", + projectIdentifiers: { android: "projectId", ios: "projectId"}, }); const projectService: IProjectService = testInjector.resolve(ProjectServiceLib.ProjectService); @@ -458,7 +459,8 @@ describe("Project Service Tests", () => { const projectDataService = testInjector.resolve("projectDataService"); const projectData: any = { projectDir: "projectDir", - projectId: "projectId" + projectId: "projectId", + projectIdentifiers: { android: "projectId", ios: "projectId"} }; let returnedProjectData: any = null; diff --git a/test/services/debug-service.ts b/test/services/debug-service.ts index 8050cd0e55..3f14bbc9f0 100644 --- a/test/services/debug-service.ts +++ b/test/services/debug-service.ts @@ -102,8 +102,8 @@ describe("debugService", () => { describe("debug", () => { const getDebugData = (deviceIdentifier?: string): IDebugData => ({ - applicationIdentifier: "org.nativescript.app1", deviceIdentifier: deviceIdentifier || defaultDeviceIdentifier, + applicationIdentifier: "org.nativescript.app1", projectDir: "/Users/user/app1", projectName: "app1" }); diff --git a/test/stubs.ts b/test/stubs.ts index 61c02ca43d..c57d872c52 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -247,11 +247,13 @@ export class ProjectDataStub implements IProjectData { projectDir: string; projectName: string; get platformsDir(): string { - return ""; + return this.plafromsDir; } set platformsDir(value) { + this.plafromsDir = value; } projectFilePath: string; + projectIdentifiers: Mobile.IProjectIdentifier; projectId: string; dependencies: any; nsConfig: any; @@ -259,6 +261,7 @@ export class ProjectDataStub implements IProjectData { devDependencies: IStringDictionary; projectType: string; appResourcesDirectoryPath: string; + private plafromsDir: string = ""; public androidManifestPath: string; public infoPlistPath: string; public appGradlePath: string; @@ -267,6 +270,8 @@ export class ProjectDataStub implements IProjectData { public initializeProjectData(projectDir?: string): void { this.projectDir = this.projectDir || projectDir; + this.projectIdentifiers = { android: "", ios: ""}; + this.projectId = ""; } public initializeProjectDataFromContent(): void { return;