@ui5/task-adaptation
Version:
Custom task for ui5-builder which allows building UI5 Flexibility Adaptation Projects for SAP BTP, Cloud Foundry environment
118 lines • 5.11 kB
JavaScript
import { dotToUnderscore, isManifestChange } from "./util/commonUtil.js";
import FilesUtil from "./util/filesUtil.js";
import ResourceUtil from "./util/resourceUtil.js";
import { posix as path } from "path";
import { moveFile, moveFiles } from "./util/movingHandler/fileMoveHandler.js";
const CHANGES_EXT = ".change";
export default class AppVariant {
files;
resources;
id;
reference;
layer;
content;
prefix = "";
movedFiles = new Map();
renaming = new Map();
static async fromWorkspace(workspace, projectNamespace) {
const EXTENSIONS_TO_PROCESS = "js,json,xml,html,properties,change,appdescr_variant,ctrl_variant,ctrl_variant_change,ctrl_variant_management_change,variant,fioriversion,codeChange,xmlViewChange,context";
const resources = await workspace.byGlob(`/**/*.{${EXTENSIONS_TO_PROCESS}}`);
const files = await ResourceUtil.toFileMap(resources, projectNamespace);
return new AppVariant(files, resources);
}
static fromFiles(files) {
return new AppVariant(files);
}
constructor(files, resources) {
this.files = files;
this.resources = resources;
const manifestString = files.get("manifest.appdescr_variant");
this.validateManifest(manifestString);
const { reference, id, layer, content } = JSON.parse(manifestString);
this.reference = reference;
this.id = id;
this.layer = layer;
this.content = content;
// Prefix is a subfolder for the app variant to store js, fragments,
// annotations and i18n files. It can be anything, but for convenience
// it is an app variant id.
this.prefix = dotToUnderscore(this.id);
}
getProcessedFiles() {
const { files, renamingPaths } = moveFiles(this.files, this.prefix, this.id);
// Directly rename files that with new paths, this ensures no conflict in further renaming
// In later remaming it's not possible to find correct prefix of moved files
return FilesUtil.rename(files, renamingPaths);
}
;
/**
* Since we moved files, we need to update paths where they were referenced.
* To do this we use renameMap function along with renaming ids.
*/
getRenamingForMovedFiles() {
const renaming = new Map();
const slashToDot = (str) => str.replaceAll("\/", ".");
this.renaming.forEach((newPath, oldPath) => {
renaming.set(slashToDot(oldPath), slashToDot(newPath));
});
return renaming;
}
;
getProcessedManifestChanges() {
// Order: manifest changes first, then *.change files
const manifestChanges = structuredClone(this.content) ?? [];
this.files.forEach((content, filename) => {
if (filename.endsWith(CHANGES_EXT)) {
const change = JSON.parse(content);
if (isManifestChange(filename, content)) {
const { newFilename } = moveFile(filename, content, this.prefix, this.id);
this.updateRelativePaths(change, newFilename);
manifestChanges.push(change);
}
}
});
if (this.layer) {
manifestChanges.forEach(change => change.layer = this.layer ?? change.layer);
}
return manifestChanges;
}
validateManifest(manifest) {
if (!manifest) {
throw new Error("Adaptation project should contain manifest.appdescr_variant");
}
}
updateRelativePaths(change, filename) {
// TODO In future this should be handled by merger which needs to know change and target location
if (change.changeType === "appdescr_app_addAnnotationsToOData") {
for (const dataSource of Object.values(change?.content?.dataSource)) {
if (!dataSource.uri.startsWith("/")) {
const basepath = path.dirname(filename);
dataSource.uri = path.join(basepath.replace(/^\//, ""), dataSource.uri);
}
}
}
}
/**
* 3p. We not only omit files, which were moved or deleted from the resulted
* file set, but also update existing adaptation project resources with
* renamed content, otherwise flexibility-bundle will contain not renamed
* content of files.
*/
omitDeletedResources(files, projectNamespace, taskUtil) {
if (!this.resources) {
return;
}
for (const resource of this.resources) {
const relativePath = ResourceUtil.relativeToRoot(resource.getPath(), projectNamespace);
if (!files.has(relativePath)) {
taskUtil.setTag(resource, taskUtil.STANDARD_TAGS.OmitFromBuildResult, true);
if (this.movedFiles.has(relativePath)) {
const newPath = this.movedFiles.get(relativePath);
const renamedContent = files.get(newPath);
resource.setString(renamedContent);
}
}
}
}
}
//# sourceMappingURL=appVariantManager.js.map