UNPKG

@oracle/suitecloud-cli

Version:
210 lines (181 loc) 6.35 kB
/* ** Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. ** Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. */ 'use strict'; const { ERRORS } = require('./TranslationKeys'); const { FILES, FOLDERS, LINKS: { INFO }, PROJECT_ACP, PROJECT_SUITEAPP } = require('../ApplicationConstants'); const CLIException = require('../CLIException'); const FileUtils = require('../utils/FileUtils'); const path = require('path'); const NodeTranslationService = require('./NodeTranslationService'); const xml2js = require('xml2js'); const assert = require('assert'); const { lineBreak } = require('../loggers/LoggerConstants'); const MANIFEST_TAG_XML_PATH = '/manifest'; const PROJECT_TYPE_ATTRIBUTE = 'projecttype'; const MANIFEST_TAG_REGEX = '[\\s\\n]*<manifest.*>[^]*</manifest>[\\s\\n]*$'; module.exports = class ProjectInfoService { constructor(projectFolder) { assert(projectFolder); this._CACHED_PROJECT_TYPE = null; this._CACHED_PROJECT_NAME = null; this._CACHED_PUBLISHER_ID = null; this._CACHED_PROJECT_ID = null; this._projectFolder = projectFolder; } /** * This validation function has to be defined in xml2js.Parser in the "validator" option * When calling parserString this function will be executed for every tag of the xml we are * parsing. * @param {string} xmlPath Path of the tag that it's being evaluated at the current moment. * @param {Object} previousValue Existing value at this path if there is already one (e.g. this * is the second or later item in an array). * @param {Object} newValue Value of the tag that it's being evaluated at the current moment. * @throws ValidationError if the validation fails */ _validateXml(xmlPath, previousValue, newValue) { //TODO Add more cases if (xmlPath === MANIFEST_TAG_XML_PATH) { let manifestTagAttributes = newValue['$']; if (!manifestTagAttributes || !manifestTagAttributes[PROJECT_TYPE_ATTRIBUTE]) { throw new xml2js.ValidationError( NodeTranslationService.getMessage(ERRORS.XML_PROJECTTYPE_ATTRIBUTE_MISSING) ); } else if ( manifestTagAttributes[PROJECT_TYPE_ATTRIBUTE] !== PROJECT_SUITEAPP && manifestTagAttributes[PROJECT_TYPE_ATTRIBUTE] !== PROJECT_ACP ) { throw new xml2js.ValidationError( NodeTranslationService.getMessage(ERRORS.XML_PROJECTTYPE_INCORRECT) ); } } return newValue; } getProjectType() { if (!this._CACHED_PROJECT_TYPE) { this._parseManifest(); } return this._CACHED_PROJECT_TYPE; } getProjectName() { if (!this._CACHED_PROJECT_NAME) { this._parseManifest(); } return this._CACHED_PROJECT_NAME; } getPublisherId() { if (!this._CACHED_PUBLISHER_ID) { this._parseManifest(); } return this._CACHED_PUBLISHER_ID; } getProjectId() { if (!this._CACHED_PROJECT_ID) { this._parseManifest(); } return this._CACHED_PROJECT_ID; } getApplicationId() { return this.getPublisherId() + '.' + this.getProjectId(); } _parseManifest() { const manifestPath = this._getManifestPath(); const manifestString = this._getManifestString(manifestPath); let projectName; let projectType; let publisherId; let projectId; let validationError; let parser = new xml2js.Parser({ validator: this._validateXml }); parser.parseString(manifestString, function (err, result) { if (err) { const errorMessage = NodeTranslationService.getMessage(ERRORS.PROCESS_FAILED) + ' ' + NodeTranslationService.getMessage(ERRORS.FILE, manifestPath); validationError = errorMessage + ' ' + err; } if (result) { projectType = result.manifest.$.projecttype; projectName = result.manifest.projectname; publisherId = result.manifest.publisherid; projectId = result.manifest.projectid; } }); //TODO CHECK XML IS VALID if (validationError) { throw new CLIException(validationError); } this._CACHED_PROJECT_TYPE = projectType; this._CACHED_PROJECT_NAME = projectName; this._CACHED_PUBLISHER_ID = publisherId; this._CACHED_PROJECT_ID = projectId; } _getManifestPath() { const manifestPath = path.join(this._projectFolder, FILES.MANIFEST_XML); if (!FileUtils.exists(manifestPath)) { const errorMessage = NodeTranslationService.getMessage(ERRORS.PROCESS_FAILED) + ' ' + NodeTranslationService.getMessage(ERRORS.FILE_NOT_EXIST, manifestPath) + lineBreak + NodeTranslationService.getMessage(ERRORS.SEE_PROJECT_STRUCTURE, INFO.PROJECT_STRUCTURE); throw new CLIException(errorMessage); } return manifestPath; } _getManifestString(manifestPath) { const manifestString = FileUtils.readAsString(manifestPath); if (!manifestString.match(MANIFEST_TAG_REGEX)) { const errorMessage = NodeTranslationService.getMessage(ERRORS.PROCESS_FAILED) + ' ' + NodeTranslationService.getMessage(ERRORS.XML_MANIFEST_TAG_MISSING); throw new CLIException(errorMessage); } return manifestString; } hasLockAndHideFiles() { const pathToInstallationPreferences = path.join( this._projectFolder, FOLDERS.INSTALLATION_PREFERENCES ); return ( FileUtils.exists( path.join(pathToInstallationPreferences, FILES.HIDING_PREFERENCE) ) && FileUtils.exists( path.join(pathToInstallationPreferences, FILES.LOCKING_PREFERENCE) ) ); } isAccountCustomizationProject() { try { return this.getProjectType() === PROJECT_ACP; } catch (error) { return false; } } isSuiteAppProject() { try { return this.getProjectType() === PROJECT_SUITEAPP; } catch (error) { return false; } } isSuiteCloudProject() { return this.isAccountCustomizationProject() || this.isSuiteAppProject(); } checkWorkingDirectoryContainsValidProject(commandName) { if (!FileUtils.exists(path.join(this._projectFolder, FILES.MANIFEST_XML))) { const errorMessage = NodeTranslationService.getMessage(ERRORS.NOT_PROJECT_FOLDER, FILES.MANIFEST_XML, this._projectFolder, commandName) + lineBreak + NodeTranslationService.getMessage(ERRORS.SEE_PROJECT_STRUCTURE, INFO.PROJECT_STRUCTURE); throw new CLIException(errorMessage); } } };