@ui5/task-adaptation 1.4.2 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -1
- package/README.md +16 -12
- package/REUSE.toml +10 -0
- package/dist/annotationManager.d.ts +1 -1
- package/dist/annotationManager.js +5 -8
- package/dist/annotations/dataSource/dataSource.js +0 -1
- package/dist/annotations/serviceRequestor.js +3 -15
- package/dist/appVariantManager.d.ts +16 -11
- package/dist/appVariantManager.js +56 -83
- package/dist/baseAppManager.d.ts +16 -16
- package/dist/baseAppManager.js +58 -81
- package/dist/bundle.d.ts +2 -3
- package/dist/bundle.js +3834 -3490
- package/dist/cache/cacheHolder.d.ts +18 -0
- package/dist/cache/cacheHolder.js +80 -0
- package/dist/i18nManager.js +11 -9
- package/dist/index.js +34 -9
- package/dist/model/appVariantIdHierarchyItem.d.ts +5 -0
- package/dist/model/appVariantIdHierarchyItem.js +2 -0
- package/dist/model/configuration.d.ts +2 -2
- package/dist/model/language.d.ts +3 -3
- package/dist/model/language.js +11 -4
- package/dist/model/types.d.ts +3 -1
- package/dist/processors/abapProcessor.d.ts +5 -5
- package/dist/processors/abapProcessor.js +19 -7
- package/dist/processors/cfProcessor.d.ts +4 -4
- package/dist/processors/cfProcessor.js +29 -13
- package/dist/processors/processor.d.ts +4 -2
- package/dist/processors/processor.js +3 -5
- package/dist/repositories/abapRepoManager.d.ts +3 -1
- package/dist/repositories/abapRepoManager.js +24 -5
- package/dist/repositories/html5RepoManager.js +3 -2
- package/dist/util/cfUtil.d.ts +1 -0
- package/dist/util/cfUtil.js +27 -23
- package/dist/util/commonUtil.d.ts +5 -3
- package/dist/util/commonUtil.js +104 -31
- package/dist/util/filesUtil.d.ts +17 -0
- package/dist/util/filesUtil.js +49 -0
- package/dist/util/i18nMerger.d.ts +15 -20
- package/dist/util/i18nMerger.js +46 -64
- package/dist/util/renamingHandlers/manifestHandler.d.ts +6 -0
- package/dist/util/renamingHandlers/manifestHandler.js +20 -0
- package/dist/util/renamingHandlers/renamingHandler.d.ts +4 -0
- package/dist/util/renamingHandlers/renamingHandler.js +2 -0
- package/dist/util/requestUtil.d.ts +2 -1
- package/dist/util/resourceUtil.d.ts +3 -1
- package/dist/util/resourceUtil.js +15 -2
- package/eslint.config.js +20 -4
- package/package.json +28 -22
- package/scripts/rollup/bundle.d.ts +2 -3
- package/scripts/rollup/bundleDefinition.js +2 -2
- package/scripts/rollup/overrides/sap/ui/fl/Utils.js +13 -0
- package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/changes/FlexCustomData.js +13 -0
- package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/flexObjects/AnnotationChange.js +11 -0
- package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/flexObjects/AppDescriptorChange.js +68 -0
- package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/flexObjects/VariantChange.js +11 -0
- package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/flexObjects/VariantManagementChange.js +11 -0
- package/scripts/rollup/overrides/sap/ui/fl/apply/_internal/flexState/controlVariants/VariantManagementState.js +13 -0
- package/scripts/rollup/overrides/sap/ui/fl/initial/_internal/changeHandlers/ChangeHandlerRegistration.js +13 -0
- package/scripts/rollup/overrides/sap/ui/fl/initial/_internal/changeHandlers/ChangeHandlerStorage.js +14 -0
- package/scripts/rollup/project/ui5.yaml +1 -1
- package/scripts/test-integration-prep.sh +4 -0
- package/types/ui5.d.ts +10 -0
- package/dist/cache/annotationsCacheManager.d.ts +0 -8
- package/dist/cache/annotationsCacheManager.js +0 -16
- package/dist/cache/baseAppFilesCacheManager.d.ts +0 -6
- package/dist/cache/baseAppFilesCacheManager.js +0 -12
- package/dist/cache/cacheManager.d.ts +0 -16
- package/dist/cache/cacheManager.js +0 -65
- package/scripts/rollup/overrides/sap/ui/fl/Change.js +0 -74
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,20 @@
|
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
|
3
3
|
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
4
4
|
|
|
5
|
-
A list of unreleased changes can be found [here](https://github.com/SAP/ui5-task-adaptation/compare/v1.
|
|
5
|
+
A list of unreleased changes can be found [here](https://github.com/SAP/ui5-task-adaptation/compare/v1.5.0...HEAD).
|
|
6
|
+
|
|
7
|
+
<a name="v1.5.0"></a>
|
|
8
|
+
## [v1.5.0] - 2025-07-17
|
|
9
|
+
|
|
10
|
+
<a name="v1.4.3"></a>
|
|
11
|
+
## [v1.4.3] - 2025-04-17
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
- Handling undefined oAuthScopes ([#122](https://github.com/SAP/ui5-task-adaptation/issues/122)) [`ea6296b`](https://github.com/SAP/ui5-task-adaptation/commit/ea6296b143e7fcbf8ce3902499be2d4c2fea61a5)
|
|
14
|
+
- Better error handling in CF ([#121](https://github.com/SAP/ui5-task-adaptation/issues/121)) [`8ce564f`](https://github.com/SAP/ui5-task-adaptation/commit/8ce564fa847a512f4de341f14b1788bca3075da8)
|
|
15
|
+
- Get space guid correctly ([#120](https://github.com/SAP/ui5-task-adaptation/issues/120)) [`64a28ee`](https://github.com/SAP/ui5-task-adaptation/commit/64a28eefc19ecded18bd363c65a8417180200945)
|
|
16
|
+
- Create html5 repo service instance ([#118](https://github.com/SAP/ui5-task-adaptation/issues/118)) [`92a6769`](https://github.com/SAP/ui5-task-adaptation/commit/92a6769ea8704ad81bf7e65766c260bb710ab043)
|
|
17
|
+
- Audit and eslint issues [`34508cb`](https://github.com/SAP/ui5-task-adaptation/commit/34508cb013f951d68527d7a733a409ed343fe43c)
|
|
18
|
+
|
|
6
19
|
|
|
7
20
|
<a name="v1.4.2"></a>
|
|
8
21
|
## [v1.4.2] - 2025-02-25
|
|
@@ -106,6 +119,8 @@ A list of unreleased changes can be found [here](https://github.com/SAP/ui5-task
|
|
|
106
119
|
<a name="v1.0.0"></a>
|
|
107
120
|
## v1.0.0 - 2020-12-09
|
|
108
121
|
|
|
122
|
+
[v1.5.0]: https://github.com/SAP/ui5-task-adaptation/compare/v1.4.3...v1.5.0
|
|
123
|
+
[v1.4.3]: https://github.com/SAP/ui5-task-adaptation/compare/v1.4.2...v1.4.3
|
|
109
124
|
[v1.4.2]: https://github.com/SAP/ui5-task-adaptation/compare/v1.4.0...v1.4.2
|
|
110
125
|
[v1.4.0]: https://github.com/SAP/ui5-task-adaptation/compare/v1.3.3...v1.4.0
|
|
111
126
|
[v1.3.3]: https://github.com/SAP/ui5-task-adaptation/compare/v1.3.2...v1.3.3
|
package/README.md
CHANGED
|
@@ -4,28 +4,29 @@
|
|
|
4
4
|
[](https://badge.fury.io/js/@ui5%2Ftask-adaptation)
|
|
5
5
|
|
|
6
6
|
## Description
|
|
7
|
-
A custom task for [ui5-builder](https://github.com/SAP/ui5-builder) that allows
|
|
7
|
+
A custom task for [ui5-builder](https://github.com/SAP/ui5-builder) that allows you to build SAPUI5 adaptation projects for [SAP S/4HANA Cloud](https://help.sap.com/docs/bas/584e0bcbfd4a4aff91c815cefa0bce2d/6fc4e11a4b1941efa8e37a428d046f8f.html?locale=en-US&state=PRODUCTION&version=Cloud) and [SAP BTP, Cloud Foundry environment](https://help.sap.com/viewer/584e0bcbfd4a4aff91c815cefa0bce2d/Cloud/en-US/019b0c38a6b043d1a66b11d992eed290.html).
|
|
8
8
|
|
|
9
9
|
### Configuration
|
|
10
|
-
####
|
|
11
|
-
|
|
10
|
+
#### Connection
|
|
11
|
+
When creating an adaptation project, the Yeoman generator automatically generates the following connection configurations in the `ui5.yaml` file, depending on your IDE:
|
|
12
|
+
|
|
13
|
+
For local IDEs like VS Code:
|
|
12
14
|
```yaml
|
|
13
15
|
target:
|
|
14
16
|
url: example.com,
|
|
15
|
-
authenticationType:
|
|
17
|
+
authenticationType: reentranceTicket,
|
|
16
18
|
ignoreCertErrors: true | false
|
|
17
19
|
```
|
|
18
|
-
|
|
20
|
+
In SAP Business Application Studio:
|
|
19
21
|
```yaml
|
|
20
22
|
target:
|
|
21
23
|
destination: abc
|
|
22
24
|
```
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Whereas S4/Hana uses `authenticationType: reentranceTicket` to authentificate. A browser window will be opened.
|
|
25
|
+
|
|
26
|
+
For more information, see [Create an Adaptation Project](https://help.sap.com/docs/bas/developing-sap-fiori-app-in-sap-business-application-studio/create-project) (on SAP S/4HANA Cloud) or [Create an Adaptation Project](https://help.sap.com/docs/bas/developing-sap-fiori-app-in-sap-business-application-studio/create-adaptation-project-c7b455d488bc4229af7efe0311546752) (on SAP BTP, Cloud Foundry environment).
|
|
27
|
+
> [!NOTE]
|
|
28
|
+
> For SAP S/4HANA (on-premise) systems, a different builder is used.
|
|
29
|
+
|
|
29
30
|
|
|
30
31
|
## How to obtain support
|
|
31
32
|
In case you need any support, please create a [GitHub issue](https://github.com/SAP/ui5-task-adaptation/issues).
|
|
@@ -34,4 +35,7 @@ In case you need any support, please create a [GitHub issue](https://github.com/
|
|
|
34
35
|
Copyright (c) 2020 SAP SE or an SAP affiliate company. All rights reserved. This file and all other files in this repository are licensed under the Apache License, v 2.0 except as noted otherwise in the [LICENSE file](LICENSE).
|
|
35
36
|
|
|
36
37
|
## Release History
|
|
37
|
-
See [CHANGELOG.md](CHANGELOG.md).
|
|
38
|
+
See [CHANGELOG.md](CHANGELOG.md).
|
|
39
|
+
|
|
40
|
+
## Contributing
|
|
41
|
+
Please refer to the [SAP Contribution Guidelines](https://github.com/SAP/.github/blob/main/CONTRIBUTING.md) for instructions on how to contribute to ui5-task-adaptation.
|
package/REUSE.toml
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
SPDX-PackageName = "ui5-task-adaptation"
|
|
3
|
+
SPDX-PackageSupplier = "Aleksandr Suvorov <aleksandr.suvorov@sap.com>, Matthias Schmalz <matthias.schmalz@sap.com>"
|
|
4
|
+
SPDX-PackageDownloadLocation = "https://github.com/SAP/ui5-task-adaptation"
|
|
5
|
+
|
|
6
|
+
[[annotations]]
|
|
7
|
+
path = "**.**"
|
|
8
|
+
precedence = "aggregate"
|
|
9
|
+
SPDX-FileCopyrightText = "2009-2025 SAP SE or an SAP affiliate company"
|
|
10
|
+
SPDX-License-Identifier = "Apache-2.0"
|
|
@@ -10,7 +10,7 @@ export default class AnnotationManager {
|
|
|
10
10
|
private configuration;
|
|
11
11
|
constructor(configuration: IConfiguration, abapRepoManager: AbapRepoManager);
|
|
12
12
|
ANNOTATIONS_FOLDER: string;
|
|
13
|
-
process(
|
|
13
|
+
process(baseAppManifest: any, languages: Language[], id: string): Promise<Map<string, string>>;
|
|
14
14
|
private normalizeAppVariantId;
|
|
15
15
|
private updateManifestModel;
|
|
16
16
|
private createManifestModel;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import BaseAppManager from "./baseAppManager.js";
|
|
2
1
|
import DataSourceManager from "./annotations/dataSource/dataSourceManager.js";
|
|
3
2
|
import I18nManager from "./i18nManager.js";
|
|
4
3
|
import ServiceRequestor from "./annotations/serviceRequestor.js";
|
|
@@ -14,9 +13,7 @@ export default class AnnotationManager {
|
|
|
14
13
|
this.abapRepoManager = abapRepoManager;
|
|
15
14
|
}
|
|
16
15
|
ANNOTATIONS_FOLDER = "annotations";
|
|
17
|
-
async process(
|
|
18
|
-
const { id } = BaseAppManager.getIdVersion(renamedBaseAppManifest);
|
|
19
|
-
BaseAppManager.validateProperty(id, "sap.app/id");
|
|
16
|
+
async process(baseAppManifest, languages, id) {
|
|
20
17
|
const normalisedId = this.normalizeAppVariantId(id);
|
|
21
18
|
//TODO: switch to this after resolving @i18n custom model
|
|
22
19
|
const modelName = I18N_DEFAULT_MODEL_NAME; //`i18n_a9n_${normalisedId}`;
|
|
@@ -24,20 +21,20 @@ export default class AnnotationManager {
|
|
|
24
21
|
const i18nManager = new I18nManager(modelName, id, languages);
|
|
25
22
|
const serviceRequestor = new ServiceRequestor(this.configuration, this.abapRepoManager);
|
|
26
23
|
const dataSourceManager = new DataSourceManager();
|
|
27
|
-
dataSourceManager.addDataSources(
|
|
24
|
+
dataSourceManager.addDataSources(baseAppManifest["sap.app"]?.dataSources);
|
|
28
25
|
const annotationFiles = await dataSourceManager.createAnnotationFiles(languages, i18nManager, serviceRequestor);
|
|
29
26
|
const i18nFiles = i18nManager.createFiles(i18nPathName);
|
|
30
27
|
if (i18nManager.hasTranslations()) {
|
|
31
|
-
this.updateManifestModel(
|
|
28
|
+
this.updateManifestModel(baseAppManifest, modelName, i18nPathName);
|
|
32
29
|
}
|
|
33
30
|
return new Map([...annotationFiles, ...i18nFiles]);
|
|
34
31
|
}
|
|
35
32
|
normalizeAppVariantId(id, replaceWith = "") {
|
|
36
33
|
return id.replace(/[.\W]+/gi, replaceWith);
|
|
37
34
|
}
|
|
38
|
-
updateManifestModel(
|
|
35
|
+
updateManifestModel(baseAppManifest, modelName, i18nPathName) {
|
|
39
36
|
const uri = `${i18nPathName}/i18n.properties`;
|
|
40
|
-
this.enhanceManifestModel(
|
|
37
|
+
this.enhanceManifestModel(baseAppManifest, modelName, uri);
|
|
41
38
|
//TODO: switch to this after resolving @i18n custom model
|
|
42
39
|
//this.createManifestModel(renamedBaseAppManifest, modelName, uri);
|
|
43
40
|
}
|
|
@@ -4,7 +4,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
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;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import AnnotationsCacheManager from "../cache/annotationsCacheManager.js";
|
|
8
7
|
import ServerError from "../model/serverError.js";
|
|
9
8
|
import { getLogger } from "@ui5/logger";
|
|
10
9
|
import { writeTempAnnotations } from "../util/commonUtil.js";
|
|
@@ -46,20 +45,9 @@ export default class ServiceRequestor {
|
|
|
46
45
|
//old decorators are already subject of compiler error, but it works. So we
|
|
47
46
|
//wait till esbuild implement it correctly.
|
|
48
47
|
async downloadAnnotation(uri, name, language) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
cacheName += `-${language.sap}`;
|
|
53
|
-
}
|
|
54
|
-
const cacheManager = new AnnotationsCacheManager(this.configuration, cacheName);
|
|
55
|
-
log.verbose(`Getting annotation '${cacheName}' ${language} by '${uri}'`);
|
|
56
|
-
let files;
|
|
57
|
-
if (this.configuration.enableAnnotationCache) {
|
|
58
|
-
files = await cacheManager.getFiles(() => this.abapRepoManager.getAnnotationMetadata(uri), () => this.abapRepoManager.downloadAnnotationFile(uri));
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
files = await this.abapRepoManager.downloadAnnotationFile(uri);
|
|
62
|
-
}
|
|
48
|
+
uri += `?sap-language=${language.sap}`;
|
|
49
|
+
log.verbose(`Getting annotation '${name}' ${language} by '${uri}'`);
|
|
50
|
+
let files = await this.abapRepoManager.downloadAnnotationFile(uri);
|
|
63
51
|
if (!files || files.size === 0) {
|
|
64
52
|
throw new Error(`No files were fetched for '${name}' by '${uri}'`);
|
|
65
53
|
}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import { IChange } from "./model/types.js";
|
|
2
|
+
import TaskUtil from "@ui5/project/build/helpers/TaskUtil";
|
|
3
|
+
export default class AppVariant {
|
|
4
|
+
readonly files: ReadonlyMap<string, string>;
|
|
5
|
+
readonly resources?: ReadonlyArray<Resource>;
|
|
6
|
+
readonly id: string;
|
|
7
|
+
readonly reference: string;
|
|
8
|
+
readonly layer: any;
|
|
9
|
+
readonly content: any;
|
|
10
|
+
static fromWorkspace(workspace: IWorkspace, projectNamespace: string): Promise<AppVariant>;
|
|
11
|
+
static fromFiles(files: ReadonlyMap<string, string>): AppVariant;
|
|
12
|
+
private constructor();
|
|
13
|
+
getProcessedManifestChanges(): IChange[];
|
|
14
|
+
private validateManifest;
|
|
15
|
+
private updateRelativePaths;
|
|
16
|
+
omitDeletedResources(files: ReadonlyMap<string, string>, projectNamespace: string, taskUtil: TaskUtil): void;
|
|
12
17
|
}
|
|
@@ -1,101 +1,74 @@
|
|
|
1
1
|
import ResourceUtil from "./util/resourceUtil.js";
|
|
2
2
|
import { posix as path } from "path";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
const MANIFEST_CHANGES_DIR = "changes/manifest/";
|
|
4
|
+
export default class AppVariant {
|
|
5
|
+
files;
|
|
6
|
+
resources;
|
|
7
|
+
id;
|
|
8
|
+
reference;
|
|
9
|
+
layer;
|
|
10
|
+
content;
|
|
11
|
+
static async fromWorkspace(workspace, projectNamespace) {
|
|
12
|
+
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";
|
|
13
|
+
const resources = await workspace.byGlob(`/**/*.{${EXTENSIONS_TO_PROCESS}}`);
|
|
14
|
+
const files = await ResourceUtil.toFileMap(resources, projectNamespace);
|
|
15
|
+
return new AppVariant(files, resources);
|
|
12
16
|
}
|
|
13
|
-
static
|
|
14
|
-
return
|
|
17
|
+
static fromFiles(files) {
|
|
18
|
+
return new AppVariant(files);
|
|
15
19
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const basename = path.dirname(resourcePath);
|
|
27
|
-
if (basename.startsWith(changesFolder)) {
|
|
28
|
-
changes.set(resourcePath, await ResourceUtil.getString(resource));
|
|
29
|
-
resourcesByPath.set(resourcePath, resource);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
this.updateRelativePaths(changes, projectNamespace);
|
|
33
|
-
this.validateManifest(manifest);
|
|
34
|
-
const renamedChanges = renameResources(changes, manifest.reference, manifest.id);
|
|
35
|
-
renamedChanges.forEach((renamedContent, resourcePath) => {
|
|
36
|
-
const resource = resourcesByPath.get(resourcePath);
|
|
37
|
-
ResourceUtil.setString(resource, renamedContent);
|
|
38
|
-
});
|
|
20
|
+
constructor(files, resources) {
|
|
21
|
+
this.files = files;
|
|
22
|
+
this.resources = resources;
|
|
23
|
+
const manifestString = files.get("manifest.appdescr_variant");
|
|
24
|
+
this.validateManifest(manifestString);
|
|
25
|
+
const { reference, id, layer, content } = JSON.parse(manifestString);
|
|
26
|
+
this.reference = reference;
|
|
27
|
+
this.id = id;
|
|
28
|
+
this.layer = layer;
|
|
29
|
+
this.content = content;
|
|
39
30
|
}
|
|
40
|
-
|
|
41
|
-
const changesManifestFolder = path.join("changes", "manifest");
|
|
42
|
-
const resourcePath = typeof resource === "string" ? resource : resource.getPath();
|
|
43
|
-
const dirname = path.dirname(resourcePath);
|
|
44
|
-
return dirname.endsWith(changesManifestFolder);
|
|
45
|
-
}
|
|
46
|
-
static isManifestAppVariant(resource) {
|
|
47
|
-
const MANIFEST_APP_VARIANT = "manifest.appdescr_variant";
|
|
48
|
-
const basename = path.basename(resource.getPath());
|
|
49
|
-
return basename === MANIFEST_APP_VARIANT;
|
|
50
|
-
}
|
|
51
|
-
static async getAppVariantInfo(appVariantResources) {
|
|
52
|
-
let manifest;
|
|
53
|
-
const manifestChanges = [];
|
|
54
|
-
for (const resource of appVariantResources) {
|
|
55
|
-
if (this.isManifestAppVariant(resource)) {
|
|
56
|
-
manifest = await ResourceUtil.getJson(resource);
|
|
57
|
-
}
|
|
58
|
-
else if (this.isManifestChange(resource)) {
|
|
59
|
-
const content = await ResourceUtil.getString(resource);
|
|
60
|
-
manifestChanges.push(JSON.parse(content));
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
this.validateManifest(manifest);
|
|
31
|
+
getProcessedManifestChanges() {
|
|
64
32
|
// Order is important: apply manifest.json changes first, then *.change
|
|
65
33
|
// files. UI5 does the same.
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
34
|
+
const manifestChanges = structuredClone(this.content) ?? [];
|
|
35
|
+
this.files.forEach((content, filename) => {
|
|
36
|
+
if (filename.startsWith(MANIFEST_CHANGES_DIR)) {
|
|
37
|
+
const change = JSON.parse(content);
|
|
38
|
+
this.updateRelativePaths(change, filename);
|
|
39
|
+
manifestChanges.push(change);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
if (this.layer) {
|
|
43
|
+
manifestChanges.forEach(change => change.layer = this.layer ?? change.layer);
|
|
44
|
+
}
|
|
45
|
+
return manifestChanges;
|
|
73
46
|
}
|
|
74
|
-
|
|
47
|
+
validateManifest(manifest) {
|
|
75
48
|
if (!manifest) {
|
|
76
49
|
throw new Error("Adaptation project should contain manifest.appdescr_variant");
|
|
77
50
|
}
|
|
78
51
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (!dataSource.uri.startsWith("/")) {
|
|
87
|
-
const basepath = path.dirname(ResourceUtil.relativeToRoot(resourcePath, projectNamespace));
|
|
88
|
-
dataSource.uri = path.join(basepath.replace(/^\//, ""), dataSource.uri);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
changes.set(resourcePath, JSON.stringify(change));
|
|
52
|
+
updateRelativePaths(change, filename) {
|
|
53
|
+
// TODO In future this should be handled by merger which needs to know change and target location
|
|
54
|
+
if (change.changeType === "appdescr_app_addAnnotationsToOData") {
|
|
55
|
+
for (const dataSource of Object.values(change?.content?.dataSource)) {
|
|
56
|
+
if (!dataSource.uri.startsWith("/")) {
|
|
57
|
+
const basepath = path.dirname(filename);
|
|
58
|
+
dataSource.uri = path.join(basepath.replace(/^\//, ""), dataSource.uri);
|
|
92
59
|
}
|
|
93
60
|
}
|
|
94
|
-
}
|
|
61
|
+
}
|
|
95
62
|
}
|
|
96
|
-
|
|
97
|
-
if (this.
|
|
98
|
-
|
|
63
|
+
omitDeletedResources(files, projectNamespace, taskUtil) {
|
|
64
|
+
if (!this.resources) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
for (const resource of this.resources) {
|
|
68
|
+
const relativePath = ResourceUtil.relativeToRoot(resource.getPath(), projectNamespace);
|
|
69
|
+
if (!files.has(relativePath)) {
|
|
70
|
+
taskUtil.setTag(resource, taskUtil.STANDARD_TAGS.OmitFromBuildResult, true);
|
|
71
|
+
}
|
|
99
72
|
}
|
|
100
73
|
}
|
|
101
74
|
}
|
package/dist/baseAppManager.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import AppVariant from "./appVariantManager.js";
|
|
2
2
|
import IProcessor from "./processors/processor.js";
|
|
3
3
|
export interface IBaseAppResources {
|
|
4
4
|
resources: any[];
|
|
@@ -11,19 +11,19 @@ export interface IManifestIdVersion {
|
|
|
11
11
|
export interface IManifestInfo extends IManifestIdVersion {
|
|
12
12
|
i18nPath: string;
|
|
13
13
|
}
|
|
14
|
-
export default class
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
private
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
private
|
|
24
|
-
private
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
private
|
|
28
|
-
|
|
14
|
+
export default class BaseApp {
|
|
15
|
+
readonly id: string;
|
|
16
|
+
readonly version: string;
|
|
17
|
+
readonly i18nPath: string;
|
|
18
|
+
readonly files: ReadonlyMap<string, string>;
|
|
19
|
+
static fromFiles(files: ReadonlyMap<string, string>): BaseApp;
|
|
20
|
+
private constructor();
|
|
21
|
+
adapt(appVariant: AppVariant, processor: IProcessor): Promise<ReadonlyMap<string, string>>;
|
|
22
|
+
private updateAdaptationProperties;
|
|
23
|
+
private extractI18nPathFromManifest;
|
|
24
|
+
private fillAppVariantIdHierarchy;
|
|
25
|
+
private VALIDATION_RULES;
|
|
26
|
+
private validateProperty;
|
|
27
|
+
private applyDescriptorChanges;
|
|
28
|
+
private adjustAddNewModelEnhanceWith;
|
|
29
29
|
}
|
package/dist/baseAppManager.js
CHANGED
|
@@ -1,29 +1,45 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { dotToUnderscore,
|
|
1
|
+
import { AppDescriptorChange, Applier, RegistrationBuild } from "../dist/bundle.js";
|
|
2
|
+
import { dotToUnderscore, trimExtension } from "./util/commonUtil.js";
|
|
3
3
|
import BuildStrategy from "./buildStrategy.js";
|
|
4
|
-
import ResourceUtil from "./util/resourceUtil.js";
|
|
5
4
|
import { getLogger } from "@ui5/logger";
|
|
6
|
-
import { renameResources } from "./util/commonUtil.js";
|
|
7
5
|
const log = getLogger("@ui5/task-adaptation::BaseAppManager");
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
renamedBaseAppFiles.set(filepath, JSON.stringify(content));
|
|
21
|
-
return {
|
|
22
|
-
resources: this.writeToWorkspace(renamedBaseAppFiles, options.projectNamespace),
|
|
23
|
-
manifestInfo: this.getManifestInfo(content)
|
|
24
|
-
};
|
|
6
|
+
const IGNORE_FILES = [
|
|
7
|
+
"manifest-bundle.zip",
|
|
8
|
+
"Component-preload.js",
|
|
9
|
+
"sap-ui-cachebuster-info.json"
|
|
10
|
+
];
|
|
11
|
+
export default class BaseApp {
|
|
12
|
+
id;
|
|
13
|
+
version;
|
|
14
|
+
i18nPath;
|
|
15
|
+
files;
|
|
16
|
+
static fromFiles(files) {
|
|
17
|
+
return new BaseApp(files);
|
|
25
18
|
}
|
|
26
|
-
|
|
19
|
+
constructor(files) {
|
|
20
|
+
this.files = new Map([...files].filter(([filename]) => !IGNORE_FILES.includes(filename)));
|
|
21
|
+
const manifestString = files.get("manifest.json");
|
|
22
|
+
if (!manifestString) {
|
|
23
|
+
throw new Error("Original application should have manifest.json in root folder");
|
|
24
|
+
}
|
|
25
|
+
const manifest = JSON.parse(manifestString);
|
|
26
|
+
this.id = manifest["sap.app"]?.id;
|
|
27
|
+
this.version = manifest["sap.app"]?.applicationVersion?.version;
|
|
28
|
+
this.validateProperty(this.id, "sap.app/id");
|
|
29
|
+
this.validateProperty(this.version, "sap.app/applicationVersion/version");
|
|
30
|
+
this.i18nPath = this.extractI18nPathFromManifest(this.id, manifest["sap.app"]?.i18n);
|
|
31
|
+
}
|
|
32
|
+
async adapt(appVariant, processor) {
|
|
33
|
+
const files = new Map(this.files);
|
|
34
|
+
const manifest = JSON.parse(files.get("manifest.json"));
|
|
35
|
+
await processor.updateLandscapeSpecificContent(manifest, files, appVariant.id);
|
|
36
|
+
this.fillAppVariantIdHierarchy(processor, this.id, this.version, manifest);
|
|
37
|
+
this.updateAdaptationProperties(manifest);
|
|
38
|
+
await this.applyDescriptorChanges(manifest, appVariant);
|
|
39
|
+
files.set("manifest.json", JSON.stringify(manifest));
|
|
40
|
+
return files;
|
|
41
|
+
}
|
|
42
|
+
updateAdaptationProperties(content) {
|
|
27
43
|
if (content["sap.fiori"]?.cloudDevAdaptationStatus) {
|
|
28
44
|
delete content["sap.fiori"].cloudDevAdaptationStatus;
|
|
29
45
|
}
|
|
@@ -32,42 +48,21 @@ export default class BaseAppManager {
|
|
|
32
48
|
}
|
|
33
49
|
content["sap.ui5"].isCloudDevAdaptation = true;
|
|
34
50
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
static extractI18nPathFromManifest(sapAppId, i18nNode) {
|
|
47
|
-
if (typeof i18nNode === "object") {
|
|
48
|
-
return i18nNode["bundleUrl"] ? this.extractI18NFromBundleUrl(i18nNode) : this.extractI18NFromBundleName(i18nNode, sapAppId);
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
return `${sapAppId?.replaceAll(".", "/")}/${i18nNode}`;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
static extractI18NFromBundleName(i18nNode, sapAppId) {
|
|
55
|
-
return i18nNode["bundleName"].replace(sapAppId, "").replaceAll(".", "/").substring(1);
|
|
56
|
-
}
|
|
57
|
-
static extractI18NFromBundleUrl(i18nNode) {
|
|
58
|
-
return removePropertiesExtension(i18nNode["bundleUrl"]);
|
|
59
|
-
}
|
|
60
|
-
static getBaseAppManifest(baseAppFiles) {
|
|
61
|
-
const manifestContent = baseAppFiles.get("manifest.json");
|
|
62
|
-
if (manifestContent) {
|
|
63
|
-
return {
|
|
64
|
-
content: JSON.parse(manifestContent),
|
|
65
|
-
filepath: "manifest.json"
|
|
66
|
-
};
|
|
51
|
+
extractI18nPathFromManifest(sapAppId, i18nNode) {
|
|
52
|
+
if (i18nNode) {
|
|
53
|
+
if (i18nNode["bundleUrl"]) {
|
|
54
|
+
return trimExtension(i18nNode["bundleUrl"]);
|
|
55
|
+
}
|
|
56
|
+
else if (i18nNode["bundleName"]) {
|
|
57
|
+
return i18nNode["bundleName"].replace(sapAppId, "").replaceAll(".", "/").substring(1);
|
|
58
|
+
}
|
|
59
|
+
else if (typeof i18nNode === "string") {
|
|
60
|
+
return trimExtension(i18nNode);
|
|
61
|
+
}
|
|
67
62
|
}
|
|
68
|
-
|
|
63
|
+
return "i18n/i18n";
|
|
69
64
|
}
|
|
70
|
-
|
|
65
|
+
fillAppVariantIdHierarchy(processor, id, version, baseAppManifest) {
|
|
71
66
|
log.verbose("Filling up app variant hierarchy in manifest.json");
|
|
72
67
|
if (baseAppManifest["sap.ui5"] == null) {
|
|
73
68
|
baseAppManifest["sap.ui5"] = {};
|
|
@@ -78,12 +73,12 @@ export default class BaseAppManager {
|
|
|
78
73
|
const appVariantIdHierarchyItem = processor.createAppVariantHierarchyItem(id, version);
|
|
79
74
|
baseAppManifest["sap.ui5"].appVariantIdHierarchy.unshift(appVariantIdHierarchyItem);
|
|
80
75
|
}
|
|
81
|
-
|
|
76
|
+
VALIDATION_RULES = new Map([["sap.app/id", (value) => {
|
|
82
77
|
if (!value.includes(".")) {
|
|
83
78
|
throw new Error(`The original application id '${value}' should consist of multiple segments split by dot, e.g.: original.id`);
|
|
84
79
|
}
|
|
85
80
|
}]]);
|
|
86
|
-
|
|
81
|
+
validateProperty(value, property) {
|
|
87
82
|
if (!value) {
|
|
88
83
|
throw new Error(`Original application manifest should have ${property}`);
|
|
89
84
|
}
|
|
@@ -92,15 +87,12 @@ export default class BaseAppManager {
|
|
|
92
87
|
validatationRule(value);
|
|
93
88
|
}
|
|
94
89
|
}
|
|
95
|
-
|
|
90
|
+
async applyDescriptorChanges(baseAppManifest, appVariant) {
|
|
96
91
|
log.verbose("Applying appVariant changes");
|
|
97
92
|
const changesContent = new Array();
|
|
98
|
-
const i18nBundleName = dotToUnderscore(id);
|
|
99
|
-
for (const change of
|
|
100
|
-
|
|
101
|
-
change.layer = layer;
|
|
102
|
-
}
|
|
103
|
-
changesContent.push(new Change(change));
|
|
93
|
+
const i18nBundleName = dotToUnderscore(appVariant.id);
|
|
94
|
+
for (const change of appVariant.getProcessedManifestChanges()) {
|
|
95
|
+
changesContent.push(new AppDescriptorChange(change));
|
|
104
96
|
this.adjustAddNewModelEnhanceWith(change, i18nBundleName);
|
|
105
97
|
}
|
|
106
98
|
if (changesContent.length > 0) {
|
|
@@ -108,7 +100,7 @@ export default class BaseAppManager {
|
|
|
108
100
|
await Applier.applyChanges(baseAppManifest, changesContent, strategy);
|
|
109
101
|
}
|
|
110
102
|
}
|
|
111
|
-
|
|
103
|
+
adjustAddNewModelEnhanceWith(change, i18nBundleName) {
|
|
112
104
|
if (change.changeType === "appdescr_ui5_addNewModelEnhanceWith") {
|
|
113
105
|
if (change.texts == null) {
|
|
114
106
|
// We need to add texts properties to changes because not all
|
|
@@ -120,20 +112,5 @@ export default class BaseAppManager {
|
|
|
120
112
|
change.texts.i18n = i18nBundleName + "/" + change.texts.i18n;
|
|
121
113
|
}
|
|
122
114
|
}
|
|
123
|
-
static writeToWorkspace(baseAppFiles, projectNamespace) {
|
|
124
|
-
const IGNORE_FILES = [
|
|
125
|
-
"manifest-bundle.zip",
|
|
126
|
-
"Component-preload.js",
|
|
127
|
-
"sap-ui-cachebuster-info.json"
|
|
128
|
-
];
|
|
129
|
-
const resources = [];
|
|
130
|
-
for (let filename of baseAppFiles.keys()) {
|
|
131
|
-
if (!IGNORE_FILES.includes(filename)) {
|
|
132
|
-
const resource = ResourceUtil.createResource(filename, projectNamespace, baseAppFiles.get(filename));
|
|
133
|
-
resources.push(resource);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return resources;
|
|
137
|
-
}
|
|
138
115
|
}
|
|
139
116
|
//# sourceMappingURL=baseAppManager.js.map
|
package/dist/bundle.d.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
export declare const RegistrationBuild: () => void;
|
|
2
2
|
|
|
3
3
|
export declare class Applier {
|
|
4
|
-
static applyChanges(manifest: any, changes:
|
|
4
|
+
static applyChanges(manifest: any, changes: AppDescriptorChange[], strategy: any): Promise<void>;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export declare class
|
|
7
|
+
export declare class AppDescriptorChange {
|
|
8
8
|
constructor(change: any);
|
|
9
9
|
getLayer(): string;
|
|
10
|
-
_oDefinition: any;
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
export declare class V2MetadataConverter {
|