diff --git a/lib/bootstrap.ts b/lib/bootstrap.ts index 08dcd977b3..be6f999e1d 100644 --- a/lib/bootstrap.ts +++ b/lib/bootstrap.ts @@ -6,7 +6,7 @@ $injector.require("options", "./options"); $injector.require("nativescript-cli", "./nativescript-cli"); $injector.require("projectData", "./project-data"); -$injector.require("projectDataService", "./services/project-data-service"); +$injector.requirePublic("projectDataService", "./services/project-data-service"); $injector.requirePublic("projectService", "./services/project-service"); $injector.require("androidProjectService", "./services/android-project-service"); $injector.require("iOSEntitlementsService", "./services/ios-entitlements-service"); diff --git a/lib/common b/lib/common index e9eb609609..ac6bcbe2e2 160000 --- a/lib/common +++ b/lib/common @@ -1 +1 @@ -Subproject commit e9eb609609425271c8f991e04d00a292cef1b37f +Subproject commit ac6bcbe2e260a2c95efab002542216be45507c0a diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index 38f10db72e..fe99a67c6e 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -63,14 +63,18 @@ interface IProjectData extends IProjectDir { appDirectoryPath: string; appResourcesDirectoryPath: string; projectType: string; + nsConfig: any; /** * Initializes project data with the given project directory. If none supplied defaults to --path option or cwd. * @param {string} projectDir Project root directory. * @returns {void} */ initializeProjectData(projectDir?: string): void; + initializeProjectDataFromContent(packageJsonContent: string, nsconfigContent: string, projectDir?: string): void; getAppDirectoryPath(projectDir?: string): string; + getAppDirectoryRelativePath(): string; getAppResourcesDirectoryPath(projectDir?: string): string; + getAppResourcesRelativeDirectoryPath(): string; } interface IProjectDataService { diff --git a/lib/project-data.ts b/lib/project-data.ts index 90f358b72e..b7f4cd59ba 100644 --- a/lib/project-data.ts +++ b/lib/project-data.ts @@ -1,5 +1,6 @@ import * as constants from "./constants"; import * as path from "path"; +import { parseJson } from "./common/helpers"; import { EOL } from "os"; interface IProjectType { @@ -32,6 +33,7 @@ export class ProjectData implements IProjectData { public projectFilePath: string; public projectId: string; public projectName: string; + public nsConfig: any; get appDirectoryPath(): string { return this.getAppDirectoryPath(); } @@ -51,37 +53,68 @@ export class ProjectData implements IProjectData { public initializeProjectData(projectDir?: string): void { projectDir = projectDir || this.$projectHelper.projectDir; + // If no project found, projectDir should be null if (projectDir) { - const projectFilePath = path.join(projectDir, this.$staticConfig.PROJECT_FILE_NAME); - let data: any = null; + const projectFilePath = this.getProjectFilePath(projectDir); if (this.$fs.exists(projectFilePath)) { - let fileContent: any = null; - try { - fileContent = this.$fs.readJson(projectFilePath); - data = fileContent[this.$staticConfig.CLIENT_NAME_KEY_IN_PROJECT_FILE]; - } catch (err) { - this.$errors.failWithoutHelp(`The project file ${this.projectFilePath} is corrupted. ${EOL}` + - `Consider restoring an earlier version from your source control or backup.${EOL}` + - `Additional technical info: ${err.toString()}`); - } - - if (data) { - this.projectDir = projectDir; - this.projectName = this.$projectHelper.sanitizeName(path.basename(projectDir)); - this.platformsDir = path.join(projectDir, constants.PLATFORMS_DIR_NAME); - this.projectFilePath = projectFilePath; - this.projectId = data.id; - this.dependencies = fileContent.dependencies; - this.devDependencies = fileContent.devDependencies; - this.projectType = this.getProjectType(); - - return; - } + let packageJsonContent: any = null; + packageJsonContent = this.$fs.readText(projectFilePath); + const nsConfigContent: any = this.getNsConfigContent(projectDir); + + this.initializeProjectDataFromContent(packageJsonContent, nsConfigContent, projectDir); } + + return; + } + + this.errorInvalidProject(projectDir); + } + + public initializeProjectDataFromContent(packageJsonContent: string, nsconfigContent: string, projectDir?: string): void { + projectDir = projectDir || this.$projectHelper.projectDir || ""; + const projectFilePath = this.getProjectFilePath(projectDir); + // If no project found, projectDir should be null + let nsData: any = null; + let nsConfig: any = null; + let packageJsonData: any = null; + + try { + packageJsonData = parseJson(packageJsonContent); + nsData = packageJsonData[this.$staticConfig.CLIENT_NAME_KEY_IN_PROJECT_FILE]; + } catch (err) { + this.$errors.failWithoutHelp(`The project file ${this.projectFilePath} is corrupted. ${EOL}` + + `Consider restoring an earlier version from your source control or backup.${EOL}` + + `Additional technical info: ${err.toString()}`); + } + + try { + nsConfig = nsconfigContent ? parseJson(nsconfigContent) : null; + } catch (err) { + this.$errors.failWithoutHelp(`The NativeScript configuration file ${constants.CONFIG_NS_FILE_NAME} is corrupted. ${EOL}` + + `Consider restoring an earlier version from your source control or backup.${EOL}` + + `Additional technical info: ${err.toString()}`); } + if (nsData) { + this.projectDir = projectDir; + 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.dependencies = packageJsonData.dependencies; + this.devDependencies = packageJsonData.devDependencies; + this.projectType = this.getProjectType(); + this.nsConfig = nsConfig; + + return; + } + + this.errorInvalidProject(projectDir); + } + + private errorInvalidProject(projectDir: string): void { const currentDir = path.resolve("."); this.$logger.trace(`Unable to find project. projectDir: ${projectDir}, options.path: ${this.$options.path}, ${currentDir}`); @@ -89,21 +122,24 @@ export class ProjectData implements IProjectData { this.$errors.fail("No project found at or above '%s' and neither was a --path specified.", projectDir || this.$options.path || currentDir); } + private getProjectFilePath(projectDir: string): string { + return path.join(projectDir, this.$staticConfig.PROJECT_FILE_NAME); + } + public getAppResourcesDirectoryPath(projectDir?: string): string { if (!projectDir) { projectDir = this.projectDir; } - const configNS = this.getNsConfig(projectDir); - let absoluteAppResourcesDirPath: string; - - if (configNS && configNS[constants.CONFIG_NS_APP_RESOURCES_ENTRY]) { - const appResourcesDirPath = configNS[constants.CONFIG_NS_APP_RESOURCES_ENTRY]; + return path.resolve(projectDir, this.getAppResourcesRelativeDirectoryPath()); + } - absoluteAppResourcesDirPath = path.resolve(projectDir, appResourcesDirPath); + public getAppResourcesRelativeDirectoryPath(): string { + if (this.nsConfig && this.nsConfig[constants.CONFIG_NS_APP_RESOURCES_ENTRY]) { + return this.nsConfig[constants.CONFIG_NS_APP_RESOURCES_ENTRY]; } - return absoluteAppResourcesDirPath || path.join(this.getAppDirectoryPath(projectDir), constants.APP_RESOURCES_FOLDER_NAME); + return path.join(this.getAppDirectoryRelativePath(), constants.APP_RESOURCES_FOLDER_NAME); } public getAppDirectoryPath(projectDir?: string): string { @@ -111,26 +147,25 @@ export class ProjectData implements IProjectData { projectDir = this.projectDir; } - const configNS = this.getNsConfig(projectDir); - let absoluteAppDirPath: string; - - if (configNS && configNS[constants.CONFIG_NS_APP_ENTRY]) { - const appDirPath = configNS[constants.CONFIG_NS_APP_ENTRY]; + return path.resolve(projectDir, this.getAppDirectoryRelativePath()); + } - absoluteAppDirPath = path.resolve(projectDir, appDirPath); + public getAppDirectoryRelativePath(): string { + if (this.nsConfig && this.nsConfig[constants.CONFIG_NS_APP_ENTRY]) { + return this.nsConfig[constants.CONFIG_NS_APP_ENTRY]; } - return absoluteAppDirPath || path.join(projectDir, constants.APP_FOLDER_NAME); + return constants.APP_FOLDER_NAME; } - private getNsConfig(projectDir: string): Object { + private getNsConfigContent(projectDir: string): string { const configNSFilePath = path.join(projectDir, constants.CONFIG_NS_FILE_NAME); if (!this.$fs.exists(configNSFilePath)) { return null; } - return this.$fs.readJson(configNSFilePath); + return this.$fs.readText(configNSFilePath); } private getProjectType(): string { diff --git a/lib/services/project-data-service.ts b/lib/services/project-data-service.ts index 46703f552d..a1bbdf1524 100644 --- a/lib/services/project-data-service.ts +++ b/lib/services/project-data-service.ts @@ -1,5 +1,6 @@ import * as path from "path"; import { ProjectData } from "../project-data"; +import { exported } from "../common/decorators"; interface IProjectFileData { projectData: any; @@ -41,6 +42,13 @@ export class ProjectDataService implements IProjectDataService { return projectDataInstance; } + @exported("projectDataService") + public getProjectDataFromContent(packageJsonContent: string, nsconfigContent: string, projectDir?: string): IProjectData { + const projectDataInstance = this.$injector.resolve(ProjectData); + projectDataInstance.initializeProjectDataFromContent(packageJsonContent, nsconfigContent, projectDir); + return projectDataInstance; + } + private getValue(projectDir: string, propertyName: string): any { const projectData = this.getProjectFileData(projectDir).projectData; diff --git a/test/project-data.ts b/test/project-data.ts index 44209529d7..6789af8b4c 100644 --- a/test/project-data.ts +++ b/test/project-data.ts @@ -15,7 +15,8 @@ describe("projectData", () => { testInjector.register("fs", { exists: () => true, - readJson: (): any => null + readJson: (): any => null, + readText: (): any => null }); testInjector.register("staticConfig", { @@ -41,11 +42,11 @@ describe("projectData", () => { const fs = testInjector.resolve("fs"); fs.exists = (filePath: string) => filePath && path.basename(filePath) === "package.json"; - fs.readJson = () => ({ + fs.readText = () => (JSON.stringify({ nativescript: {}, dependencies: dependencies, devDependencies: devDependencies - }); + })); const projectHelper: IProjectHelper = testInjector.resolve("projectHelper"); projectHelper.projectDir = "projectDir"; diff --git a/test/stubs.ts b/test/stubs.ts index 3e32a11841..7d77dba3bf 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -253,6 +253,7 @@ export class ProjectDataStub implements IProjectData { projectFilePath: string; projectId: string; dependencies: any; + nsConfig: any; get appDirectoryPath(): string { return this.getAppDirectoryPath(); } @@ -264,6 +265,9 @@ export class ProjectDataStub implements IProjectData { public initializeProjectData(projectDir?: string): void { this.projectDir = this.projectDir || projectDir; } + public initializeProjectDataFromContent(): void { + return; + } public getAppResourcesDirectoryPath(projectDir?: string): string { if (!projectDir) { projectDir = this.projectDir; @@ -284,6 +288,9 @@ export class ProjectDataStub implements IProjectData { return absoluteAppResourcesDirPath || path.join(projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME); } + public getAppResourcesRelativeDirectoryPath(): string { + return ""; + } public getAppDirectoryPath(projectDir?: string): string { if (!projectDir) { projectDir = this.projectDir; @@ -291,6 +298,9 @@ export class ProjectDataStub implements IProjectData { return path.join(projectDir, "app") || ""; } + public getAppDirectoryRelativePath(): string { + return ""; + } } export class PlatformProjectServiceStub extends EventEmitter implements IPlatformProjectService {