UNPKG

nativescript

Version:

Command-line interface for building NativeScript projects

275 lines • 13.8 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProjectChangesService = void 0; const path = require("path"); const constants_1 = require("../constants"); const helpers_1 = require("../common/helpers"); const _ = require("lodash"); const yok_1 = require("../common/yok"); const prepareInfoFileName = ".nsprepareinfo"; class ProjectChangesInfo { get hasChanges() { return (this.nativeChanged || this.appResourcesChanged || this.configChanged || this.signingChanged); } get changesRequireBuild() { return this.appResourcesChanged || this.nativeChanged; } get changesRequirePrepare() { return this.appResourcesChanged || this.signingChanged; } } class ProjectChangesService { constructor($devicePlatformsConstants, $fs, $logger, $options, $hooksService, $nodeModulesDependenciesBuilder) { this.$devicePlatformsConstants = $devicePlatformsConstants; this.$fs = $fs; this.$logger = $logger; this.$options = $options; this.$hooksService = $hooksService; this.$nodeModulesDependenciesBuilder = $nodeModulesDependenciesBuilder; } get currentChanges() { return this._changesInfo; } async checkForChanges(platformData, projectData, prepareData) { this._changesInfo = new ProjectChangesInfo(); const isNewPrepareInfo = await this.ensurePrepareInfo(platformData, projectData, prepareData); if (!isNewPrepareInfo) { let platformResourcesDir = path.join(projectData.appResourcesDirectoryPath, platformData.normalizedPlatformName); if (!this.$fs.exists(platformResourcesDir) && platformData.platformNameLowerCase === this.$devicePlatformsConstants.visionOS.toLowerCase()) { platformResourcesDir = path.join(projectData.appResourcesDirectoryPath, this.$devicePlatformsConstants.iOS); } this._changesInfo.appResourcesChanged = this.containsNewerFiles(platformResourcesDir, projectData); this.$nodeModulesDependenciesBuilder .getProductionDependencies(projectData.projectDir, projectData.ignoredDependencies) .filter((dep) => dep.nativescript && this.$fs.exists(path.join(dep.directory, constants_1.PLATFORMS_DIR_NAME, platformData.platformNameLowerCase))) .forEach((dep) => { this._changesInfo.nativeChanged = this._changesInfo.nativeChanged || this.containsNewerFiles(path.join(dep.directory, constants_1.PLATFORMS_DIR_NAME, platformData.platformNameLowerCase), projectData) || this.isFileModified(path.join(dep.directory, constants_1.PACKAGE_JSON_FILE_NAME)); }); if (!this._changesInfo.nativeChanged) { this._prepareInfo.projectFileHash = this.getProjectFileStrippedHash(projectData.projectDir, platformData); this._changesInfo.nativeChanged = this.isProjectFileChanged(projectData.projectDir, platformData); } // If this causes too much rebuilds of the plugins or uncecessary builds for Android, move overrideCocoapods to prepareInfo. this._changesInfo.nsConfigChanged = this.filesChanged([ path.join(projectData.projectDir, constants_1.CONFIG_FILE_NAME_JS), path.join(projectData.projectDir, constants_1.CONFIG_FILE_NAME_TS), path.join(projectData.projectDir, constants_1.CONFIG_NS_FILE_NAME), ]); this._changesInfo.nativeChanged = this._changesInfo.nativeChanged || this._changesInfo.nsConfigChanged; this.$logger.trace(`Set nativeChanged to ${this._changesInfo.nativeChanged}.`); if (platformData.platformNameLowerCase === this.$devicePlatformsConstants.iOS.toLowerCase()) { this._changesInfo.configChanged = this.filesChanged([ path.join(platformResourcesDir, platformData.configurationFileName), path.join(platformResourcesDir, "LaunchScreen.storyboard"), path.join(platformResourcesDir, constants_1.BUILD_XCCONFIG_FILE_NAME), ]); } else { this._changesInfo.configChanged = this.filesChanged([ path.join(platformResourcesDir, platformData.configurationFileName), path.join(platformResourcesDir, constants_1.APP_GRADLE_FILE_NAME), ]); } this.$logger.trace(`Set value of configChanged to ${this._changesInfo.configChanged}`); } if (!prepareData.nativePrepare || !prepareData.nativePrepare.skipNativePrepare) { await platformData.platformProjectService.checkForChanges(this._changesInfo, prepareData, projectData); } if (!!prepareData.release !== !!this._prepareInfo.release) { this.$logger.trace(`Setting all setting to true. Current options are: `, prepareData, " old prepare info is: ", this._prepareInfo); this._changesInfo.appResourcesChanged = true; this._changesInfo.configChanged = true; this._prepareInfo.release = prepareData.release; } if (this._changesInfo.appResourcesChanged) { this.$logger.trace(`Set configChanged to true, appResourcesChanged is: ${this._changesInfo.appResourcesChanged}`); this._changesInfo.configChanged = true; } if (this._changesInfo.hasChanges) { this._prepareInfo.changesRequireBuild = this._changesInfo.changesRequireBuild; this._prepareInfo.time = new Date().toString(); if (this._prepareInfo.changesRequireBuild) { this._prepareInfo.changesRequireBuildTime = this._prepareInfo.time; } } this._changesInfo.nativePlatformStatus = this._prepareInfo.nativePlatformStatus; this.$logger.trace("checkForChanges returns", this._changesInfo); return this._changesInfo; } getPrepareInfoFilePath(platformData) { const prepareInfoFilePath = path.join(platformData.projectRoot, prepareInfoFileName); return prepareInfoFilePath; } getPrepareInfo(platformData) { if (this.$options.hostProjectPath) { // TODO: always prepare for now until we decide where to keep the .nsprepareinfo file when embedding return null; } const prepareInfoFilePath = this.getPrepareInfoFilePath(platformData); let prepareInfo = null; if (this.$fs.exists(prepareInfoFilePath)) { try { prepareInfo = this.$fs.readJson(prepareInfoFilePath); } catch (e) { prepareInfo = null; } } return prepareInfo; } async savePrepareInfo(platformData, projectData, prepareData) { if (!this._prepareInfo) { await this.ensurePrepareInfo(platformData, projectData, prepareData); } if (this.$options.hostProjectPath) { // TODO: do not save for now until we decide where to keep the .nsprepareinfo file when embedding return null; } const prepareInfoFilePath = this.getPrepareInfoFilePath(platformData); this.$fs.writeJson(prepareInfoFilePath, this._prepareInfo); } async setNativePlatformStatus(platformData, projectData, addedPlatform) { this._prepareInfo = this._prepareInfo || this.getPrepareInfo(platformData); if (this._prepareInfo && addedPlatform.nativePlatformStatus === "3" /* NativePlatformStatus.alreadyPrepared */) { this._prepareInfo.nativePlatformStatus = addedPlatform.nativePlatformStatus; } else { this._prepareInfo = { nativePlatformStatus: addedPlatform.nativePlatformStatus, }; } await this.savePrepareInfo(platformData, projectData, null); } async ensurePrepareInfo(platformData, projectData, prepareData) { this._prepareInfo = this.getPrepareInfo(platformData); if (this._prepareInfo) { const prepareInfoFile = path.join(platformData.projectRoot, prepareInfoFileName); this._outputProjectMtime = this.$fs .getFsStats(prepareInfoFile) .mtime.getTime(); this._outputProjectCTime = this.$fs .getFsStats(prepareInfoFile) .ctime.getTime(); return false; } const nativePlatformStatus = !prepareData.nativePrepare || !prepareData.nativePrepare.skipNativePrepare ? "2" /* NativePlatformStatus.requiresPrepare */ : "1" /* NativePlatformStatus.requiresPlatformAdd */; this._prepareInfo = { time: "", nativePlatformStatus, release: prepareData.release, changesRequireBuild: true, projectFileHash: this.getProjectFileStrippedHash(projectData.projectDir, platformData), changesRequireBuildTime: null, }; this._outputProjectMtime = 0; this._outputProjectCTime = 0; this._changesInfo = this._changesInfo || new ProjectChangesInfo(); this._changesInfo.appResourcesChanged = true; this._changesInfo.configChanged = true; this._changesInfo.nativeChanged = true; this._changesInfo.nsConfigChanged = true; return true; } getProjectFileStrippedHash(projectDir, platformData) { const projectFilePath = path.join(projectDir, constants_1.PACKAGE_JSON_FILE_NAME); const projectFileContents = this.$fs.readJson(projectFilePath); const relevantProperties = ["dependencies"]; const projectFileStrippedContents = _.pick(projectFileContents, relevantProperties); // _(this.$devicePlatformsConstants) // .keys() // .map(k => k.toLowerCase()) // .difference([platformData.platformNameLowerCase]) // .each(otherPlatform => { // delete projectFileContents.nativescript[`tns-${otherPlatform}`]; // }); return (0, helpers_1.getHash)(JSON.stringify(projectFileStrippedContents)); } isProjectFileChanged(projectDir, platformData) { const projectFileStrippedContentsHash = this.getProjectFileStrippedHash(projectDir, platformData); const prepareInfo = this.getPrepareInfo(platformData); return projectFileStrippedContentsHash !== prepareInfo.projectFileHash; } filesChanged(files) { for (const file of files) { if (this.$fs.exists(file)) { const fileStats = this.$fs.getFsStats(file); if (fileStats.mtime.getTime() >= this._outputProjectMtime || fileStats.ctime.getTime() >= this._outputProjectCTime) { return true; } } } return false; } containsNewerFiles(dir, projectData) { const dirName = path.basename(dir); this.$logger.trace(`containsNewerFiles will check ${dir}`); if (_.startsWith(dirName, ".")) { return false; } if (this.isFileModified(dir)) { this.$logger.trace(`containsNewerFiles returns true for ${dir} as the dir itself has been modified.`); return true; } const files = this.$fs.readDirectory(dir); for (const file of files) { const filePath = path.join(dir, file); const fileStats = this.$fs.getFsStats(filePath); const changed = this.isFileModified(filePath, fileStats); if (changed) { this.$logger.trace(`containsNewerFiles returns true for ${dir}. The modified file is ${filePath}`); return true; } if (fileStats.isDirectory()) { if (this.containsNewerFiles(filePath, projectData)) { this.$logger.trace(`containsNewerFiles returns true for ${dir}.`); return true; } } } return false; } isFileModified(filePath, filePathStats) { filePathStats = filePathStats || this.$fs.getFsStats(filePath); let changed = filePathStats.mtime.getTime() >= this._outputProjectMtime || filePathStats.ctime.getTime() >= this._outputProjectCTime; if (!changed) { const lFileStats = this.$fs.getLsStats(filePath); changed = lFileStats.mtime.getTime() >= this._outputProjectMtime || lFileStats.ctime.getTime() >= this._outputProjectCTime; } return changed; } } exports.ProjectChangesService = ProjectChangesService; __decorate([ (0, helpers_1.hook)("checkForChanges") ], ProjectChangesService.prototype, "checkForChanges", null); yok_1.injector.register("projectChangesService", ProjectChangesService); //# sourceMappingURL=project-changes-service.js.map