@ui5/task-adaptation
Version:
Custom task for ui5-builder which allows building UI5 Flexibility Adaptation Projects for SAP BTP, Cloud Foundry environment
102 lines • 4.89 kB
JavaScript
import ResourceUtil from "./util/resourceUtil.js";
import { posix as path } from "path";
import { renameResources } from "./util/commonUtil.js";
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";
export default class AppVariantManager {
static async process(appVariantResources, projectNamespace, taskUtil) {
for (const resource of appVariantResources) {
this.omitFiles(resource, taskUtil);
}
await this.updateChanges(appVariantResources, projectNamespace);
return this.getAppVariantInfo(appVariantResources);
}
static getAppVariantResourcesToProcess(workspace) {
return workspace.byGlob(`/**/*.{${EXTENSIONS_TO_PROCESS}}`);
}
static async updateChanges(appVariantResources, projectNamespace) {
const changesFolder = ResourceUtil.getResourcePath(projectNamespace, "changes");
const changes = new Map();
const resourcesByPath = new Map();
let manifest;
for (const resource of appVariantResources) {
if (this.isManifestAppVariant(resource)) {
manifest = await ResourceUtil.getJson(resource);
}
const resourcePath = resource.getPath();
const basename = path.dirname(resourcePath);
if (basename.startsWith(changesFolder)) {
changes.set(resourcePath, await ResourceUtil.getString(resource));
resourcesByPath.set(resourcePath, resource);
}
}
this.updateRelativePaths(changes, projectNamespace);
this.validateManifest(manifest);
const renamedChanges = renameResources(changes, manifest.reference, manifest.id);
renamedChanges.forEach((renamedContent, resourcePath) => {
const resource = resourcesByPath.get(resourcePath);
ResourceUtil.setString(resource, renamedContent);
});
}
static isManifestChange(resource) {
const changesManifestFolder = path.join("changes", "manifest");
const resourcePath = typeof resource === "string" ? resource : resource.getPath();
const dirname = path.dirname(resourcePath);
return dirname.endsWith(changesManifestFolder);
}
static isManifestAppVariant(resource) {
const MANIFEST_APP_VARIANT = "manifest.appdescr_variant";
const basename = path.basename(resource.getPath());
return basename === MANIFEST_APP_VARIANT;
}
static async getAppVariantInfo(appVariantResources) {
let manifest;
const manifestChanges = [];
for (const resource of appVariantResources) {
if (this.isManifestAppVariant(resource)) {
manifest = await ResourceUtil.getJson(resource);
}
else if (this.isManifestChange(resource)) {
const content = await ResourceUtil.getString(resource);
manifestChanges.push(JSON.parse(content));
}
}
this.validateManifest(manifest);
// Order is important: apply manifest.json changes first, then *.change
// files. UI5 does the same.
const changes = (manifest.content ?? []).concat(manifestChanges);
return {
id: manifest.id,
reference: manifest.reference,
layer: manifest.layer,
changes
};
}
static validateManifest(manifest) {
if (!manifest) {
throw new Error("Adaptation project should contain manifest.appdescr_variant");
}
}
// TODO In future this should be handled by merger which needs to know change and target location
static updateRelativePaths(changes, projectNamespace) {
changes.forEach((jsonString, resourcePath) => {
if (this.isManifestChange(resourcePath)) {
const change = JSON.parse(jsonString);
if (change.changeType === "appdescr_app_addAnnotationsToOData") {
for (const dataSource of Object.values(change.content.dataSource)) {
if (!dataSource.uri.startsWith("/")) {
const basepath = path.dirname(ResourceUtil.relativeToRoot(resourcePath, projectNamespace));
dataSource.uri = path.join(basepath.replace(/^\//, ""), dataSource.uri);
}
}
changes.set(resourcePath, JSON.stringify(change));
}
}
});
}
static omitFiles(resource, taskUtil) {
if (this.isManifestAppVariant(resource) || this.isManifestChange(resource)) {
taskUtil.setTag(resource, taskUtil.STANDARD_TAGS.OmitFromBuildResult, true);
}
}
}
//# sourceMappingURL=appVariantManager.js.map