Skip to content

Commit 64a973d

Browse files
committed
refactor(project-data): read app_resources dir from nsconfig.json
Refactor the project-data service to read a config.json for the 'app_resources' property entry, which points relatively to the App_Resources directory. All references to app/App_Resources now retrieve the path from said service. To keep the service backwards compatible, if no config.json is present, or the app_resources entry isn't available, location defaults to projectDir/app/App_Resources.
1 parent 8125d4b commit 64a973d

18 files changed

+96
-47
lines changed

lib/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ export const BUILD_DIR = "build";
2828
export const OUTPUTS_DIR = "outputs";
2929
export const APK_DIR = "apk";
3030
export const RESOURCES_DIR = "res";
31+
export const CONFIG_NS_FILE_NAME = "nsconfig.json";
32+
export const CONFIG_NS_APP_RESOURCES_ENTRY = "app_resources";
3133

3234
export class PackageVersion {
3335
static NEXT = "next";

lib/definitions/project.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,14 @@ interface IProjectData extends IProjectDir {
6161
dependencies: any;
6262
devDependencies: IStringDictionary;
6363
appDirectoryPath: string;
64-
appResourcesDirectoryPath: string;
6564
projectType: string;
6665
/**
6766
* Initializes project data with the given project directory. If none supplied defaults to --path option or cwd.
6867
* @param {string} projectDir Project root directory.
6968
* @returns {void}
7069
*/
7170
initializeProjectData(projectDir?: string): void;
71+
getAppResourcesDirectoryPath(projectDir?: string): string;
7272
}
7373

7474
interface IProjectDataService {

lib/project-data.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ export class ProjectData implements IProjectData {
6969
this.platformsDir = path.join(projectDir, constants.PLATFORMS_DIR_NAME);
7070
this.projectFilePath = projectFilePath;
7171
this.appDirectoryPath = path.join(projectDir, constants.APP_FOLDER_NAME);
72-
this.appResourcesDirectoryPath = path.join(projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME);
7372
this.projectId = data.id;
7473
this.dependencies = fileContent.dependencies;
7574
this.devDependencies = fileContent.devDependencies;
@@ -87,6 +86,27 @@ export class ProjectData implements IProjectData {
8786
this.$errors.fail("No project found at or above '%s' and neither was a --path specified.", projectDir || this.$options.path || currentDir);
8887
}
8988

89+
public getAppResourcesDirectoryPath(projectDir?: string): string {
90+
if (!projectDir) {
91+
projectDir = this.projectDir;
92+
}
93+
94+
const configNSFilePath = path.join(projectDir, constants.CONFIG_NS_FILE_NAME);
95+
let absoluteAppResourcesDirPath: string;
96+
97+
if (this.$fs.exists(configNSFilePath)) {
98+
const configNS = this.$fs.readJson(configNSFilePath);
99+
100+
if (configNS && configNS[constants.CONFIG_NS_APP_RESOURCES_ENTRY]) {
101+
const appResourcesDirPath = configNS[constants.CONFIG_NS_APP_RESOURCES_ENTRY];
102+
103+
absoluteAppResourcesDirPath = path.resolve(projectDir, appResourcesDirPath);
104+
}
105+
}
106+
107+
return absoluteAppResourcesDirPath || path.join(projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME);
108+
}
109+
90110
private getProjectType(): string {
91111
let detectedProjectType = _.find(ProjectData.PROJECT_TYPES, (projectType) => projectType.isDefaultProjectType).type;
92112

lib/providers/project-files-provider.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import { ProjectFilesProviderBase } from "../common/services/project-files-provi
66
export class ProjectFilesProvider extends ProjectFilesProviderBase {
77
constructor(private $platformsData: IPlatformsData,
88
$mobileHelper: Mobile.IMobileHelper,
9-
$options:IOptions) {
10-
super($mobileHelper, $options);
9+
$options: IOptions) {
10+
super($mobileHelper, $options);
1111
}
1212

13-
private static INTERNAL_NONPROJECT_FILES = [ "**/*.ts" ];
13+
private static INTERNAL_NONPROJECT_FILES = ["**/*.ts"];
1414

1515
public mapFilePath(filePath: string, platform: string, projectData: IProjectData, projectFilesConfig: IProjectFilesConfig): string {
1616
const platformData = this.$platformsData.getPlatformData(platform.toLowerCase(), projectData);
@@ -23,14 +23,14 @@ export class ProjectFilesProvider extends ProjectFilesProviderBase {
2323
mappedFilePath = path.join(platformData.appDestinationDirectoryPath, path.relative(projectData.projectDir, parsedFilePath));
2424
}
2525

26-
const appResourcesDirectoryPath = path.join(constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME);
26+
const appResourcesDirectoryPath = projectData.getAppResourcesDirectoryPath();
2727
const platformSpecificAppResourcesDirectoryPath = path.join(appResourcesDirectoryPath, platformData.normalizedPlatformName);
2828
if (parsedFilePath.indexOf(appResourcesDirectoryPath) > -1 && parsedFilePath.indexOf(platformSpecificAppResourcesDirectoryPath) === -1) {
2929
return null;
3030
}
3131

3232
if (parsedFilePath.indexOf(platformSpecificAppResourcesDirectoryPath) > -1) {
33-
const appResourcesRelativePath = path.relative(path.join(projectData.projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME,
33+
const appResourcesRelativePath = path.relative(path.join(projectData.getAppResourcesDirectoryPath(),
3434
platformData.normalizedPlatformName), parsedFilePath);
3535
mappedFilePath = path.join(platformData.platformProjectService.getAppResourcesDestinationDirectoryPath(projectData), appResourcesRelativePath);
3636
}

lib/services/android-project-service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
252252
shell.sed('-i', /__PROJECT_NAME__/, this.getProjectNameFromId(projectData), gradleSettingsFilePath);
253253

254254
// will replace applicationId in app/App_Resources/Android/app.gradle if it has not been edited by the user
255-
const userAppGradleFilePath = path.join(projectData.appResourcesDirectoryPath, this.$devicePlatformsConstants.Android, "app.gradle");
255+
const userAppGradleFilePath = path.join(projectData.getAppResourcesDirectoryPath(), this.$devicePlatformsConstants.Android, "app.gradle");
256256

257257
try {
258258
shell.sed('-i', /__PACKAGE__/, projectData.projectId, userAppGradleFilePath);
@@ -374,7 +374,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
374374
}
375375

376376
public ensureConfigurationFileInAppResources(projectData: IProjectData): void {
377-
const originalAndroidManifestFilePath = path.join(projectData.appResourcesDirectoryPath, this.$devicePlatformsConstants.Android, this.getPlatformData(projectData).configurationFileName);
377+
const originalAndroidManifestFilePath = path.join(projectData.getAppResourcesDirectoryPath(), this.$devicePlatformsConstants.Android, this.getPlatformData(projectData).configurationFileName);
378378

379379
const manifestExists = this.$fs.exists(originalAndroidManifestFilePath);
380380

lib/services/app-files-updater.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,12 @@ export class AppFilesUpdater {
4545

4646
protected readSourceDir(): string[] {
4747
const tnsDir = path.join(this.appSourceDirectoryPath, constants.TNS_MODULES_FOLDER_NAME);
48-
return this.fs.enumerateFilesInDirectorySync(this.appSourceDirectoryPath, null, { includeEmptyDirectories: true }).filter(dirName => dirName !== tnsDir);
48+
const defaultAppResourcesDir = path.join(this.appSourceDirectoryPath, constants.APP_RESOURCES_FOLDER_NAME);
49+
return this.fs.enumerateFilesInDirectorySync(this.appSourceDirectoryPath, null, { includeEmptyDirectories: true }).filter(dirName => dirName !== tnsDir).filter(dirName => !dirName.startsWith(defaultAppResourcesDir));
4950
}
5051

5152
protected resolveAppSourceFiles(): string[] {
52-
// Copy all files from app dir, but make sure to exclude tns_modules
53+
// Copy all files from app dir, but make sure to exclude tns_modules and App_Resources
5354
let sourceFiles = this.readSourceDir();
5455

5556
if (this.options.release) {

lib/services/ios-entitlements-service.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import * as path from "path";
2-
import * as constants from "../constants";
32
import { PlistSession } from "plist-merge-patch";
43

54
export class IOSEntitlementsService {
@@ -14,8 +13,7 @@ export class IOSEntitlementsService {
1413

1514
private getDefaultAppEntitlementsPath(projectData: IProjectData) : string {
1615
const entitlementsName = IOSEntitlementsService.DefaultEntitlementsName;
17-
const entitlementsPath = path.join(projectData.projectDir,
18-
constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME,
16+
const entitlementsPath = path.join(projectData.getAppResourcesDirectoryPath(),
1917
this.$mobileHelper.normalizePlatformName(this.$devicePlatformsConstants.iOS),
2018
entitlementsName);
2119
return entitlementsPath;

lib/services/ios-project-service.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -759,9 +759,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
759759

760760
private getInfoPlistPath(projectData: IProjectData): string {
761761
return path.join(
762-
projectData.projectDir,
763-
constants.APP_FOLDER_NAME,
764-
constants.APP_RESOURCES_FOLDER_NAME,
762+
projectData.getAppResourcesDirectoryPath(),
765763
this.getPlatformData(projectData).normalizedPlatformName,
766764
this.getPlatformData(projectData).configurationFileName
767765
);
@@ -781,7 +779,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
781779

782780
private async mergeInfoPlists(buildOptions: IRelease, projectData: IProjectData): Promise<void> {
783781
const projectDir = projectData.projectDir;
784-
const infoPlistPath = path.join(projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME, this.getPlatformData(projectData).normalizedPlatformName, this.getPlatformData(projectData).configurationFileName);
782+
const infoPlistPath = path.join(projectData.getAppResourcesDirectoryPath(), this.getPlatformData(projectData).normalizedPlatformName, this.getPlatformData(projectData).configurationFileName);
785783
this.ensureConfigurationFileInAppResources();
786784

787785
if (!this.$fs.exists(infoPlistPath)) {
@@ -1211,7 +1209,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
12111209
}
12121210
}
12131211

1214-
const appResourcesXcconfigPath = path.join(projectData.projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME, this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig");
1212+
const appResourcesXcconfigPath = path.join(projectData.getAppResourcesDirectoryPath(), this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig");
12151213
if (this.$fs.exists(appResourcesXcconfigPath)) {
12161214
await this.mergeXcconfigFiles(appResourcesXcconfigPath, pluginsXcconfigFilePath);
12171215
}
@@ -1266,7 +1264,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
12661264
}
12671265

12681266
private getBuildXCConfigFilePath(projectData: IProjectData): string {
1269-
const buildXCConfig = path.join(projectData.appResourcesDirectoryPath,
1267+
const buildXCConfig = path.join(projectData.getAppResourcesDirectoryPath(),
12701268
this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig");
12711269
return buildXCConfig;
12721270
}
@@ -1328,7 +1326,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
13281326
const choicePersist = await this.$prompter.promptForChoice("Do you want to make teamId: " + teamId + " a persistent choice for your app?", choicesPersist);
13291327
switch (choicesPersist.indexOf(choicePersist)) {
13301328
case 0:
1331-
const xcconfigFile = path.join(projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig");
1329+
const xcconfigFile = path.join(projectData.getAppResourcesDirectoryPath(), this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig");
13321330
this.$fs.appendFile(xcconfigFile, "\nDEVELOPMENT_TEAM = " + teamId + "\n");
13331331
break;
13341332
case 1:
@@ -1346,8 +1344,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
13461344
}
13471345

13481346
private validateApplicationIdentifier(projectData: IProjectData): void {
1349-
const projectDir = projectData.projectDir;
1350-
const infoPlistPath = path.join(projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME, this.getPlatformData(projectData).normalizedPlatformName, this.getPlatformData(projectData).configurationFileName);
1347+
const infoPlistPath = path.join(projectData.getAppResourcesDirectoryPath(), this.getPlatformData(projectData).normalizedPlatformName, this.getPlatformData(projectData).configurationFileName);
13511348
const mergedPlistPath = this.getPlatformData(projectData).configurationFilePath;
13521349

13531350
if (!this.$fs.exists(infoPlistPath) || !this.$fs.exists(mergedPlistPath)) {

lib/services/livesync/livesync-service.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,8 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
525525
}
526526
}
527527

528+
pattern.push(projectData.getAppResourcesDirectoryPath());
529+
528530
const currentWatcherInfo = this.liveSyncProcessesInfo[liveSyncData.projectDir].watcherInfo;
529531

530532
if (!currentWatcherInfo || currentWatcherInfo.pattern !== pattern) {

lib/services/prepare-platform-js-service.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export class PreparePlatformJSService extends PreparePlatformService implements
3636
public async preparePlatform(config: IPreparePlatformJSInfo): Promise<void> {
3737
if (!config.changesInfo || config.changesInfo.appFilesChanged || config.changesInfo.changesRequirePrepare) {
3838
await this.copyAppFiles(config);
39+
this.copyAppResourcesFiles(config);
3940
}
4041

4142
if (config.changesInfo && !config.changesInfo.changesRequirePrepare) {
@@ -101,6 +102,13 @@ export class PreparePlatformJSService extends PreparePlatformService implements
101102
this.$errors.failWithoutHelp(`Processing node_modules failed. ${error}`);
102103
}
103104
}
105+
106+
private copyAppResourcesFiles(config: IPreparePlatformJSInfo) {
107+
const appDestinationDirectoryPath = path.join(config.platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME);
108+
const appResourcesSourcePath = config.projectData.getAppResourcesDirectoryPath();
109+
110+
shell.cp("-Rf", appResourcesSourcePath, appDestinationDirectoryPath);
111+
}
104112
}
105113

106114
$injector.register("preparePlatformJSService", PreparePlatformJSService);

lib/services/project-changes-service.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ export class ProjectChangesService implements IProjectChangesService {
6060
this._changesInfo = new ProjectChangesInfo();
6161
if (!this.ensurePrepareInfo(platform, projectData, projectChangesOptions)) {
6262
this._newFiles = 0;
63-
this._changesInfo.appFilesChanged = this.containsNewerFiles(projectData.appDirectoryPath, projectData.appResourcesDirectoryPath, projectData);
63+
this._changesInfo.appFilesChanged = this.containsNewerFiles(projectData.appDirectoryPath, projectData.getAppResourcesDirectoryPath(), projectData);
6464
this._changesInfo.packageChanged = this.isProjectFileChanged(projectData, platform);
65-
this._changesInfo.appResourcesChanged = this.containsNewerFiles(projectData.appResourcesDirectoryPath, null, projectData);
65+
this._changesInfo.appResourcesChanged = this.containsNewerFiles(projectData.getAppResourcesDirectoryPath(), null, projectData);
6666
/*done because currently all node_modules are traversed, a possible improvement could be traversing only the production dependencies*/
6767
this._changesInfo.nativeChanged = this.containsNewerFiles(
6868
path.join(projectData.projectDir, NODE_MODULES_FOLDER_NAME),
@@ -73,7 +73,7 @@ export class ProjectChangesService implements IProjectChangesService {
7373
if (this._newFiles > 0 || this._changesInfo.nativeChanged) {
7474
this._changesInfo.modulesChanged = true;
7575
}
76-
const platformResourcesDir = path.join(projectData.appResourcesDirectoryPath, platformData.normalizedPlatformName);
76+
const platformResourcesDir = path.join(projectData.getAppResourcesDirectoryPath(), platformData.normalizedPlatformName);
7777
if (platform === this.$devicePlatformsConstants.iOS.toLowerCase()) {
7878
this._changesInfo.configChanged = this.filesChanged([path.join(platformResourcesDir, platformData.configurationFileName),
7979
path.join(platformResourcesDir, "LaunchScreen.storyboard"),
@@ -282,7 +282,7 @@ export class ProjectChangesService implements IProjectChangesService {
282282
return true;
283283
}
284284
const projectDir = projectData.projectDir;
285-
if (_.startsWith(path.join(projectDir, file), projectData.appResourcesDirectoryPath)) {
285+
if (_.startsWith(path.join(projectDir, file), projectData.getAppResourcesDirectoryPath())) {
286286
return true;
287287
}
288288
if (_.startsWith(file, NODE_MODULES_FOLDER_NAME)) {

lib/services/project-service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ export class ProjectService implements IProjectService {
112112

113113
private async ensureAppResourcesExist(projectDir: string): Promise<void> {
114114
const appPath = path.join(projectDir, constants.APP_FOLDER_NAME),
115-
appResourcesDestinationPath = path.join(appPath, constants.APP_RESOURCES_FOLDER_NAME);
115+
appResourcesDestinationPath = this.$projectData.getAppResourcesDirectoryPath(projectDir);
116116

117117
if (!this.$fs.exists(appResourcesDestinationPath)) {
118118
this.$fs.createDirectory(appResourcesDestinationPath);

test/ios-entitlements-service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ describe("IOSEntitlements Service Tests", () => {
1919
const testInjector = new yok.Yok();
2020

2121
testInjector.register('platformsData', stubs.PlatformsDataStub);
22+
testInjector.register('projectData', stubs.ProjectDataStub);
2223
testInjector.register("logger", stubs.LoggerStub);
2324
testInjector.register('iOSEntitlementsService', IOSEntitlementsService);
2425

@@ -46,7 +47,7 @@ describe("IOSEntitlements Service Tests", () => {
4647
injector = createTestInjector();
4748

4849
platformsData = injector.resolve("platformsData");
49-
projectData = <IProjectData>platformsData.getPlatformData();
50+
projectData = injector.resolve("projectData");
5051
projectData.projectName = 'testApp';
5152

5253
projectData.platformsDir = temp.mkdirSync("platformsDir");

test/ios-project-service.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ import { Utils } from "../lib/common/utils";
2929
import { CocoaPodsService } from "../lib/services/cocoapods-service";
3030
import { NpmInstallationManager } from "../lib/npm-installation-manager";
3131
import { NodePackageManager } from "../lib/node-package-manager";
32-
import * as constants from "../lib/constants";
3332

3433
import { assert } from "chai";
3534
import { IOSProvisionService } from "../lib/services/ios-provision-service";
3635
import { SettingsService } from "../lib/common/test/unit-tests/stubs";
36+
import { ProjectDataStub } from "../test/stubs";
3737
import temp = require("temp");
3838

3939
temp.track();
@@ -65,12 +65,13 @@ function createTestInjector(projectPath: string, projectName: string): IInjector
6565
testInjector.register("iOSEntitlementsService", IOSEntitlementsService);
6666
testInjector.register("logger", LoggerLib.Logger);
6767
testInjector.register("options", OptionsLib.Options);
68-
testInjector.register("projectData", {
68+
const projectData = Object.assign({}, ProjectDataStub, {
6969
platformsDir: path.join(projectPath, "platforms"),
7070
projectName: projectName,
7171
projectPath: projectPath,
7272
projectFilePath: path.join(projectPath, "package.json")
7373
});
74+
testInjector.register("projectData", projectData);
7475
testInjector.register("projectHelper", {});
7576
testInjector.register("xcodeSelectService", {});
7677
testInjector.register("staticConfig", ConfigLib.StaticConfig);
@@ -796,8 +797,7 @@ describe("Merge Project XCConfig files", () => {
796797

797798
iOSEntitlementsService = testInjector.resolve("iOSEntitlementsService");
798799

799-
appResourcesXcconfigPath = path.join(projectData.projectDir, constants.APP_FOLDER_NAME,
800-
constants.APP_RESOURCES_FOLDER_NAME, "iOS", "build.xcconfig");
800+
appResourcesXcconfigPath = path.join(projectData.getAppResourcesDirectoryPath(), "iOS", "build.xcconfig");
801801
appResourceXCConfigContent = `CODE_SIGN_IDENTITY = iPhone Distribution
802802
// To build for device with XCode 8 you need to specify your development team. More info: https://developer.apple.com/library/prerelease/content/releasenotes/DeveloperTools/RN-Xcode/Introduction.html
803803
// DEVELOPMENT_TEAM = YOUR_TEAM_ID;

test/platform-service.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,6 @@ describe('Platform Service Tests', () => {
445445
const projectData = testInjector.resolve("projectData");
446446
projectData.projectDir = testDirData.tempFolder;
447447
projectData.appDirectoryPath = testDirData.appFolderPath;
448-
projectData.appResourcesDirectoryPath = path.join(testDirData.appFolderPath, "App_Resources");
449448
projectData.projectName = "app";
450449

451450
platformService = testInjector.resolve("platformService");

0 commit comments

Comments
 (0)