UNPKG

@ui5/task-adaptation

Version:

Custom task for ui5-builder which allows building UI5 Flexibility Adaptation Projects for SAP BTP, Cloud Foundry environment

159 lines 7.11 kB
import { AppDescriptorChange, Applier, RegistrationBuild } from "../dist/bundle.js"; import { trimExtension } from "./util/commonUtil.js"; import BuildStrategy from "./buildStrategy.js"; import { getLogger } from "@ui5/logger"; const log = getLogger("@ui5/task-adaptation::BaseAppManager"); const IGNORE_FILES = [ "manifest-bundle.zip", "Component-preload.js", "sap-ui-cachebuster-info.json" ]; /** * Processes files to replace .js file content with corresponding -dbg.js * content and remove -dbg.js * @param files - Map of all files * @returns Map with .js files replaced by -dbg.js content where applicable */ export function preProcessFiles(files) { const processedFiles = new Map(files); // Find all -dbg.js files that have corresponding .js files for (const [filename, content] of files) { if (filename.endsWith("-dbg.js")) { const correspondingJsFile = filename.replace("-dbg.js", ".js"); if (files.has(correspondingJsFile)) { // Replace the .js file content with the -dbg.js content processedFiles.set(correspondingJsFile, content); processedFiles.delete(filename); } } else if (filename.endsWith("-dbg.js.map")) { const correspondingJsFile = filename.replace("-dbg.js.map", ".js"); if (files.has(correspondingJsFile)) { processedFiles.delete(filename); } } if (IGNORE_FILES.some(ignoredFile => ignoredFile === filename)) { processedFiles.delete(filename); } } return processedFiles; } export default class BaseApp { id; version; i18nPath; files; static fromFiles(files) { return new BaseApp(files); } constructor(files) { this.files = preProcessFiles(files); const manifestString = files.get("manifest.json"); if (!manifestString) { throw new Error("Original application should have manifest.json in root folder"); } const manifest = JSON.parse(manifestString); this.id = manifest["sap.app"]?.id; this.version = manifest["sap.app"]?.applicationVersion?.version; this.validateProperty(this.id, "sap.app/id"); this.validateProperty(this.version, "sap.app/applicationVersion/version"); this.i18nPath = this.extractI18nPathFromManifest(this.id, manifest["sap.app"]?.i18n); } async adapt(appVariant, processor) { const files = new Map(this.files); const manifest = JSON.parse(files.get("manifest.json")); manifest["sap.app"].id = appVariant.id; await processor.updateLandscapeSpecificContent(manifest, files, appVariant.id, appVariant.prefix); this.updateComponentName(manifest, this.id); this.fillAppVariantIdHierarchy(processor, appVariant.reference, this.version, manifest); this.updateAdaptationProperties(manifest); await this.applyDescriptorChanges(manifest, appVariant); files.set("manifest.json", JSON.stringify(manifest)); return files; } updateComponentName(manifest, id) { if (manifest["sap.ui5"] == null) { manifest["sap.ui5"] = {}; } if (manifest["sap.ui5"].componentName == null) { manifest["sap.ui5"].componentName = id; } } updateAdaptationProperties(content) { if (content["sap.fiori"]?.cloudDevAdaptationStatus) { delete content["sap.fiori"].cloudDevAdaptationStatus; } if (content["sap.ui5"] == null) { content["sap.ui5"] = {}; } content["sap.ui5"].isCloudDevAdaptation = true; } extractI18nPathFromManifest(sapAppId, i18nNode) { if (i18nNode) { if (i18nNode["bundleUrl"]) { return trimExtension(i18nNode["bundleUrl"]); } else if (i18nNode["bundleName"]) { return i18nNode["bundleName"].replace(sapAppId, "").replaceAll(".", "/").substring(1); } else if (typeof i18nNode === "string") { return trimExtension(i18nNode); } } return "i18n/i18n"; } VALIDATION_RULES = new Map([["sap.app/id", (value) => { if (!value.includes(".")) { // https://help.sap.com/docs/bas/developing-sap-fiori-app-in-sap-business-application-studio/releasing-sap-fiori-application-to-be-extensible-in-adaptation-projects-on-sap-s-4hana-cloud // In the manifest.json file, make sure that the attribute // sap.app/id has at least 2 segments. throw new Error(`The original application id '${value}' should consist of multiple segments split by dot, e.g.: original.id`); } }]]); validateProperty(value, property) { if (!value) { throw new Error(`Original application manifest should have ${property}`); } let validatationRule = this.VALIDATION_RULES.get(property); if (validatationRule) { validatationRule(value); } } async applyDescriptorChanges(baseAppManifest, appVariant) { log.verbose("Applying appVariant changes"); const changesContent = new Array(); const i18nBundleName = appVariant.prefix; for (const change of appVariant.getProcessedManifestChanges()) { changesContent.push(new AppDescriptorChange(change)); this.adjustAddNewModelEnhanceWith(change, i18nBundleName); } if (changesContent.length > 0) { const strategy = new BuildStrategy(RegistrationBuild); await Applier.applyChanges(baseAppManifest, changesContent, strategy); } } fillAppVariantIdHierarchy(processor, id, version, baseAppManifest) { log.verbose("Filling up app variant hierarchy in manifest.json"); if (baseAppManifest["sap.ui5"] == null) { baseAppManifest["sap.ui5"] = {}; } if (baseAppManifest["sap.ui5"].appVariantIdHierarchy == null) { baseAppManifest["sap.ui5"].appVariantIdHierarchy = []; } const appVariantIdHierarchyItem = processor.createAppVariantHierarchyItem(id, version); baseAppManifest["sap.ui5"].appVariantIdHierarchy.unshift(appVariantIdHierarchyItem); } adjustAddNewModelEnhanceWith(change, i18nBundleName) { if (change.changeType === "appdescr_ui5_addNewModelEnhanceWith") { if (change.texts == null) { // We need to add texts properties to changes because not all // have texts property. Changes without texts property can // causes issues in bundle.js This is needed for now, and will // be removed as soon as change merger in openUI5 is updated change.texts = { i18n: change.content?.bundleUrl || "i18n/i18n.properties" }; } change.texts.i18n = i18nBundleName + "/" + change.texts.i18n; } } } //# sourceMappingURL=baseAppManager.js.map