@ui5/task-adaptation 1.6.5-rc.1 → 1.6.5-rc.3
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 +12 -1
- package/REUSE.toml +1 -1
- package/dist/appVariantManager.js +5 -2
- package/dist/cache/cacheHolder.js +8 -7
- package/dist/cache/cachedResource.d.ts +4 -0
- package/dist/cache/cachedResource.js +2 -0
- package/dist/index.js +1 -1
- package/dist/landscapeConfiguration.js +42 -14
- package/dist/model/configuration.d.ts +3 -3
- package/dist/model/configuration.js +1 -1
- package/dist/model/types.d.ts +1 -0
- package/dist/previewManager.js +7 -1
- package/dist/repositories/abapProvider.d.ts +1 -1
- package/dist/repositories/abapProvider.js +3 -18
- package/dist/repositories/abapRepository.d.ts +6 -5
- package/dist/repositories/abapRepository.js +10 -11
- package/dist/repositories/html5Repository.d.ts +9 -5
- package/dist/repositories/html5Repository.js +21 -32
- package/dist/repositories/localRepository.d.ts +6 -9
- package/dist/repositories/localRepository.js +12 -22
- package/dist/repositories/repository.d.ts +3 -5
- package/dist/util/filesUtil.d.ts +2 -0
- package/dist/util/filesUtil.js +7 -0
- package/dist/util/validator/abapValidator.d.ts +8 -0
- package/dist/util/validator/abapValidator.js +26 -0
- package/dist/util/validator/cfValidator.d.ts +6 -0
- package/dist/util/validator/cfValidator.js +8 -0
- package/dist/util/validator/validator.d.ts +6 -0
- package/dist/util/validator/validator.js +4 -0
- package/package.json +5 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,16 @@
|
|
|
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.6.5-rc.
|
|
5
|
+
A list of unreleased changes can be found [here](https://github.com/SAP/ui5-task-adaptation/compare/v1.6.5-rc.3...HEAD).
|
|
6
|
+
|
|
7
|
+
<a name="v1.6.5-rc.3"></a>
|
|
8
|
+
## [v1.6.5-rc.3] - 2026-04-27
|
|
9
|
+
### Reverts
|
|
10
|
+
- Release 1.6.5-rc.0
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
<a name="v1.6.5-rc.2"></a>
|
|
14
|
+
## [v1.6.5-rc.2] - 2026-04-14
|
|
6
15
|
|
|
7
16
|
<a name="v1.6.5-rc.1"></a>
|
|
8
17
|
## [v1.6.5-rc.1] - 2026-04-13
|
|
@@ -185,6 +194,8 @@ A list of unreleased changes can be found [here](https://github.com/SAP/ui5-task
|
|
|
185
194
|
<a name="v1.0.0"></a>
|
|
186
195
|
## v1.0.0 - 2020-12-09
|
|
187
196
|
|
|
197
|
+
[v1.6.5-rc.3]: https://github.com/SAP/ui5-task-adaptation/compare/v1.6.5-rc.2...v1.6.5-rc.3
|
|
198
|
+
[v1.6.5-rc.2]: https://github.com/SAP/ui5-task-adaptation/compare/v1.6.5-rc.1...v1.6.5-rc.2
|
|
188
199
|
[v1.6.5-rc.1]: https://github.com/SAP/ui5-task-adaptation/compare/v1.6.4-rc.3...v1.6.5-rc.1
|
|
189
200
|
[v1.6.4-rc.3]: https://github.com/SAP/ui5-task-adaptation/compare/v1.6.4-rc.2...v1.6.4-rc.3
|
|
190
201
|
[v1.6.4-rc.2]: https://github.com/SAP/ui5-task-adaptation/compare/v1.6.4-rc.1...v1.6.4-rc.2
|
package/REUSE.toml
CHANGED
|
@@ -7,4 +7,4 @@ SPDX-PackageDownloadLocation = "https://github.com/SAP/ui5-task-adaptation"
|
|
|
7
7
|
path = "**.**"
|
|
8
8
|
precedence = "aggregate"
|
|
9
9
|
SPDX-FileCopyrightText = "2009-2025 SAP SE or an SAP affiliate company"
|
|
10
|
-
SPDX-License-Identifier = "Apache-2.0"
|
|
10
|
+
SPDX-License-Identifier = "Apache-2.0"
|
|
@@ -62,18 +62,21 @@ export default class AppVariant {
|
|
|
62
62
|
}
|
|
63
63
|
;
|
|
64
64
|
getProcessedManifestChanges() {
|
|
65
|
-
// Order: manifest changes first, then *.change files
|
|
65
|
+
// Order: manifest changes first, then *.change files sorted by creation ASC
|
|
66
66
|
const manifestChanges = structuredClone(this.content) ?? [];
|
|
67
|
+
const changeFileChanges = [];
|
|
67
68
|
this.files.forEach((content, filename) => {
|
|
68
69
|
if (filename.endsWith(CHANGES_EXT)) {
|
|
69
70
|
const change = JSON.parse(content);
|
|
70
71
|
if (isManifestChange(filename, content)) {
|
|
71
72
|
const { newFilename } = moveFile(filename, content, this.prefix, this.id);
|
|
72
73
|
this.updateRelativePaths(change, newFilename);
|
|
73
|
-
|
|
74
|
+
changeFileChanges.push(change);
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
});
|
|
78
|
+
changeFileChanges.sort(FilesUtil.sortByTimeStamp);
|
|
79
|
+
manifestChanges.push(...changeFileChanges);
|
|
77
80
|
if (this.layer) {
|
|
78
81
|
manifestChanges.forEach(change => change.layer = this.layer ?? change.layer);
|
|
79
82
|
}
|
|
@@ -68,17 +68,18 @@ export function cached() {
|
|
|
68
68
|
return function (_target, _propertyKey, descriptor) {
|
|
69
69
|
const originalValue = descriptor.value;
|
|
70
70
|
descriptor.value = async function (...args) {
|
|
71
|
-
const
|
|
72
|
-
const cachebusterToken =
|
|
73
|
-
|
|
74
|
-
CacheHolder.
|
|
71
|
+
const cachedResource = args[0];
|
|
72
|
+
const { appName, cacheBusterToken: cachebusterToken } = cachedResource;
|
|
73
|
+
const token = await cachebusterToken;
|
|
74
|
+
let files = await CacheHolder.read(appName, token);
|
|
75
|
+
CacheHolder.clearOutdatedExcept(appName);
|
|
75
76
|
if (files.size === 0) {
|
|
76
|
-
log.verbose(`No cache for repo '${
|
|
77
|
+
log.verbose(`No cache for repo '${appName}' with token '${token}'. Fetching from HTML5 Repository.`);
|
|
77
78
|
files = await originalValue.apply(this, args);
|
|
78
|
-
await CacheHolder.write(
|
|
79
|
+
await CacheHolder.write(appName, token, files);
|
|
79
80
|
}
|
|
80
81
|
else {
|
|
81
|
-
log.verbose(`Using cached files for repo '${
|
|
82
|
+
log.verbose(`Using cached files for repo '${appName}' with token '${token}'.`);
|
|
82
83
|
}
|
|
83
84
|
return files;
|
|
84
85
|
};
|
package/dist/index.js
CHANGED
|
@@ -24,7 +24,7 @@ export default ({ workspace, options, taskUtil }) => {
|
|
|
24
24
|
// latest app variant on top. We reverse the list to process original
|
|
25
25
|
// application first and then app variants in chronological order.
|
|
26
26
|
const reversedHierarchy = appVariantIdHierarchy.toReversed();
|
|
27
|
-
const fetchFilesPromises = reversedHierarchy.map(
|
|
27
|
+
const fetchFilesPromises = reversedHierarchy.map(variant => repository.fetch(variant));
|
|
28
28
|
fetchFilesPromises.push(Promise.resolve(adaptationProject.files));
|
|
29
29
|
const appVariants = new Array();
|
|
30
30
|
const adapt = async (baseAppFiles, appVariantFiles) => {
|
|
@@ -5,21 +5,49 @@ import AbapRepository from "./repositories/abapRepository.js";
|
|
|
5
5
|
import HTML5Repository from "./repositories/html5Repository.js";
|
|
6
6
|
import LocalRepository from "./repositories/localRepository.js";
|
|
7
7
|
import AbapAnnotationManager from "./annotations/abapAnnotationManager.js";
|
|
8
|
-
import LocalAnnotationManager from "./annotations/localAnnotationManager.js";
|
|
9
|
-
import { validateObject } from "./util/commonUtil.js";
|
|
10
8
|
import CFAnnotationManager from "./annotations/cfAnnotationManager.js";
|
|
9
|
+
import CFValidator from "./util/validator/cfValidator.js";
|
|
10
|
+
import AbapValidator from "./util/validator/abapValidator.js";
|
|
11
|
+
import { isOneOf } from "./util/validator/validator.js";
|
|
12
|
+
import { LANDSCAPE_TYPES } from "./model/configuration.js";
|
|
13
|
+
import { getLogger } from "@ui5/logger";
|
|
14
|
+
import LocalAnnotationManager from "./annotations/localAnnotationManager.js";
|
|
15
|
+
const log = getLogger("@ui5/task-adaptation::LandscapeConfiguration");
|
|
11
16
|
export function initialize(configuration) {
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
const
|
|
17
|
+
const type = getTypeByConfiguration(configuration);
|
|
18
|
+
const enhancedConfig = { ...configuration, type };
|
|
19
|
+
const repository = getRepository(enhancedConfig);
|
|
20
|
+
const annotationManager = getAnnotationManager(enhancedConfig, repository);
|
|
15
21
|
return {
|
|
16
|
-
adapter: getAdapter(
|
|
22
|
+
adapter: getAdapter(enhancedConfig, annotationManager),
|
|
17
23
|
repository,
|
|
18
24
|
annotationManager
|
|
19
25
|
};
|
|
20
26
|
}
|
|
27
|
+
function getTypeByConfiguration(configuration) {
|
|
28
|
+
const validators = [
|
|
29
|
+
new CFValidator(),
|
|
30
|
+
new AbapValidator(),
|
|
31
|
+
];
|
|
32
|
+
if (isOneOf(LANDSCAPE_TYPES, configuration.type)) {
|
|
33
|
+
return configuration.type;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
log.warn("Deprecated behavior: type is not specified or invalid. Should be either 'cf' or 'abap'. Trying to detect the type based on provided configuration");
|
|
37
|
+
for (const validator of validators) {
|
|
38
|
+
try {
|
|
39
|
+
validator.validateConfiguration(configuration);
|
|
40
|
+
return validator.type;
|
|
41
|
+
}
|
|
42
|
+
catch (_error) {
|
|
43
|
+
// Continue to the next validator if validation fails
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
throw new Error("'type' should be specified in ui5.yaml configuration: 'cf' or 'abap'");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
21
49
|
function getAdapter(configuration, annotationManager) {
|
|
22
|
-
if (isPreview(
|
|
50
|
+
if (isPreview()) {
|
|
23
51
|
return new PreviewAdapter(configuration);
|
|
24
52
|
}
|
|
25
53
|
switch (configuration.type) {
|
|
@@ -32,8 +60,8 @@ function getAdapter(configuration, annotationManager) {
|
|
|
32
60
|
}
|
|
33
61
|
}
|
|
34
62
|
function getRepository(configuration) {
|
|
35
|
-
if (isLocal(
|
|
36
|
-
return new LocalRepository(
|
|
63
|
+
if (isLocal()) {
|
|
64
|
+
return new LocalRepository();
|
|
37
65
|
}
|
|
38
66
|
switch (configuration.type) {
|
|
39
67
|
case "abap":
|
|
@@ -45,7 +73,7 @@ function getRepository(configuration) {
|
|
|
45
73
|
}
|
|
46
74
|
}
|
|
47
75
|
function getAnnotationManager(configuration, repository) {
|
|
48
|
-
if (isLocal(
|
|
76
|
+
if (isLocal()) {
|
|
49
77
|
return new LocalAnnotationManager();
|
|
50
78
|
}
|
|
51
79
|
switch (configuration.type) {
|
|
@@ -57,10 +85,10 @@ function getAnnotationManager(configuration, repository) {
|
|
|
57
85
|
throw new Error(`No annotation manager found for the given configuration type '${configuration.type}'`);
|
|
58
86
|
}
|
|
59
87
|
}
|
|
60
|
-
function isLocal(
|
|
61
|
-
return process.env.ADP_BUILDER_MODE === "local"
|
|
88
|
+
function isLocal() {
|
|
89
|
+
return process.env.ADP_BUILDER_MODE === "local";
|
|
62
90
|
}
|
|
63
|
-
function isPreview(
|
|
64
|
-
return process.env.ADP_BUILDER_MODE === "preview"
|
|
91
|
+
function isPreview() {
|
|
92
|
+
return process.env.ADP_BUILDER_MODE === "preview";
|
|
65
93
|
}
|
|
66
94
|
//# sourceMappingURL=landscapeConfiguration.js.map
|
|
@@ -8,16 +8,16 @@ export interface IConfiguration {
|
|
|
8
8
|
org?: string;
|
|
9
9
|
sapCloudService?: string;
|
|
10
10
|
destination?: string;
|
|
11
|
-
type?:
|
|
12
|
-
mode?: "preview" | "local" | "default";
|
|
11
|
+
type?: LandscapeType;
|
|
13
12
|
languages?: any[] | undefined;
|
|
14
13
|
enableAnnotationCache?: boolean;
|
|
15
14
|
enableBetaFeatures?: boolean;
|
|
16
15
|
writeTempFiles?: any;
|
|
17
16
|
target?: AbapTarget & IAbapTargetMeta;
|
|
18
17
|
serviceInstanceName?: string;
|
|
19
|
-
adpDir?: string;
|
|
20
18
|
}
|
|
19
|
+
export declare const LANDSCAPE_TYPES: readonly ["cf", "abap"];
|
|
20
|
+
export type LandscapeType = typeof LANDSCAPE_TYPES[number];
|
|
21
21
|
export interface IAbapTargetMeta {
|
|
22
22
|
name?: string;
|
|
23
23
|
ignoreCertErrors?: boolean;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export const LANDSCAPE_TYPES = ["cf", "abap"];
|
|
2
2
|
//# sourceMappingURL=configuration.js.map
|
package/dist/model/types.d.ts
CHANGED
package/dist/previewManager.js
CHANGED
|
@@ -93,8 +93,14 @@ export default class PreviewManager {
|
|
|
93
93
|
const promises = new Map();
|
|
94
94
|
reuseLibs.forEach(lib => {
|
|
95
95
|
log.info(`Downloading reuse library '${lib.html5AppName}' version '${lib.html5AppVersion}'`);
|
|
96
|
+
const resource = {
|
|
97
|
+
appName: lib.html5AppName,
|
|
98
|
+
appVersion: lib.html5AppVersion,
|
|
99
|
+
appHostId: lib.html5AppHostId,
|
|
100
|
+
cacheBusterToken: Promise.resolve(lib.html5CacheBusterToken)
|
|
101
|
+
};
|
|
96
102
|
const promise = repository
|
|
97
|
-
.
|
|
103
|
+
.fetch(resource)
|
|
98
104
|
.then((libFiles) => PreviewManager.moveLibraryFiles(libFiles, lib.html5AppName, lib.name));
|
|
99
105
|
promises.set(lib.html5AppName, promise);
|
|
100
106
|
});
|
|
@@ -2,6 +2,6 @@ import type { AbapServiceProvider } from "@sap-ux/axios-extension";
|
|
|
2
2
|
import { IConfiguration } from "../model/types.js";
|
|
3
3
|
export default class AbapProvider {
|
|
4
4
|
private provider;
|
|
5
|
+
private abapValidator;
|
|
5
6
|
get({ target, destination }: IConfiguration): Promise<AbapServiceProvider>;
|
|
6
|
-
private static validateAndGetAbapTarget;
|
|
7
7
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { createAbapServiceProvider } from "@sap-ux/system-access";
|
|
2
|
-
import BtpUtils from "@sap-ux/btp-utils";
|
|
3
2
|
import { getLogger } from "@ui5/logger";
|
|
4
|
-
import
|
|
3
|
+
import AbapValidator from "../util/validator/abapValidator.js";
|
|
5
4
|
const log = getLogger("@ui5/task-adaptation::AbapProvider");
|
|
6
5
|
log.debug = (message) => log.verbose(message);
|
|
7
6
|
export default class AbapProvider {
|
|
8
7
|
provider = null;
|
|
8
|
+
abapValidator = new AbapValidator();
|
|
9
9
|
async get({ target, destination }) {
|
|
10
10
|
if (!this.provider) {
|
|
11
|
-
const abapTarget =
|
|
11
|
+
const abapTarget = this.abapValidator.validateAndGetAbapTarget(target, destination);
|
|
12
12
|
if (abapTarget) {
|
|
13
13
|
this.provider = await createAbapServiceProvider(abapTarget, { ignoreCertErrors: abapTarget.ignoreCertErrors }, true, log);
|
|
14
14
|
}
|
|
@@ -18,20 +18,5 @@ export default class AbapProvider {
|
|
|
18
18
|
}
|
|
19
19
|
return this.provider;
|
|
20
20
|
}
|
|
21
|
-
static validateAndGetAbapTarget(target, destination) {
|
|
22
|
-
if (target) {
|
|
23
|
-
// if target configuration appears, we validate that it should be
|
|
24
|
-
// either target/destination for BAS or target/url for IDE we're
|
|
25
|
-
// trying to detect is it destination for BAS or url for IDE
|
|
26
|
-
const abapTargetProperties = BtpUtils.isAppStudio() ? ["destination"] : ["url"];
|
|
27
|
-
validateObject(target, abapTargetProperties, "should be specified in ui5.yaml configuration/target");
|
|
28
|
-
return target;
|
|
29
|
-
}
|
|
30
|
-
else if (destination) {
|
|
31
|
-
log.warn("Destination is deprecated, use target/destination configuration instead");
|
|
32
|
-
return { destination };
|
|
33
|
-
}
|
|
34
|
-
throw new Error("Target should be specified in ui5.yaml configuration to connect the ABAP system");
|
|
35
|
-
}
|
|
36
21
|
}
|
|
37
22
|
//# sourceMappingURL=abapProvider.js.map
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import { IConfiguration, IMetadata
|
|
1
|
+
import { IConfiguration, IMetadata } from "../model/types.js";
|
|
2
2
|
import AbapProvider from "./abapProvider.js";
|
|
3
|
-
import { IAppVariantIdHierarchyItem } from "../model/appVariantIdHierarchyItem.js";
|
|
4
3
|
import IRepository from "./repository.js";
|
|
4
|
+
import ICachedResource from "../cache/cachedResource.js";
|
|
5
|
+
type IAbapResource = ICachedResource;
|
|
5
6
|
export default class AbapRepository implements IRepository {
|
|
6
7
|
private configuration;
|
|
7
8
|
private abapProvider;
|
|
8
9
|
constructor(configuration: IConfiguration, abapProvider?: AbapProvider);
|
|
9
|
-
|
|
10
|
-
getAppVariantIdHierarchy(id: string): Promise<IAppVariantIdHierarchyItem[]>;
|
|
10
|
+
getAppVariantIdHierarchy(id: string): Promise<IAbapResource[]>;
|
|
11
11
|
getAnnotationMetadata(uri: string): Promise<IMetadata>;
|
|
12
12
|
downloadAnnotationFile(uri: string): Promise<Map<string, any>>;
|
|
13
13
|
getMetadata(id: string): Promise<IMetadata>;
|
|
14
|
-
fetch(
|
|
14
|
+
fetch(resource: IAbapResource): Promise<Map<string, string>>;
|
|
15
15
|
}
|
|
16
|
+
export {};
|
|
@@ -27,9 +27,6 @@ export default class AbapRepository {
|
|
|
27
27
|
this.configuration = configuration;
|
|
28
28
|
this.abapProvider = abapProvider ? abapProvider : new AbapProvider();
|
|
29
29
|
}
|
|
30
|
-
fetchReuseLib(_libName, _cachebusterToken, _lib) {
|
|
31
|
-
throw new Error("Preview is not available on SAP S/4HANA On-Premise or Cloud Systems. Please create a ticket on CA-UI5-FL-ADP-BAS component.");
|
|
32
|
-
}
|
|
33
30
|
async getAppVariantIdHierarchy(id) {
|
|
34
31
|
const provider = await this.abapProvider.get(this.configuration);
|
|
35
32
|
const lrep = provider.getLayeredRepository();
|
|
@@ -37,15 +34,17 @@ export default class AbapRepository {
|
|
|
37
34
|
params: { id }
|
|
38
35
|
});
|
|
39
36
|
if (response.status === 200) {
|
|
40
|
-
|
|
37
|
+
const hierarchy = JSON.parse(response.data)?.appVariantIdHierarchy;
|
|
38
|
+
return hierarchy.map(item => ({
|
|
39
|
+
appName: item.repoName,
|
|
40
|
+
cacheBusterToken: Promise.resolve(item.cachebusterToken)
|
|
41
|
+
}));
|
|
41
42
|
}
|
|
42
43
|
else if (this.configuration.appName) {
|
|
43
44
|
// Fallback to old API on old ABAP backend or CF for backward compatibility
|
|
44
|
-
const metadataResponse = await this.getMetadata(id);
|
|
45
45
|
return [{
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
cachebusterToken: metadataResponse.changedOn
|
|
46
|
+
appName: this.configuration.appName,
|
|
47
|
+
cacheBusterToken: this.getMetadata(id).then(metadata => metadata.changedOn),
|
|
49
48
|
}];
|
|
50
49
|
}
|
|
51
50
|
throw new Error(`App variant id hierarchy for app id '${id}' is not provided`);
|
|
@@ -78,8 +77,8 @@ export default class AbapRepository {
|
|
|
78
77
|
id
|
|
79
78
|
};
|
|
80
79
|
}
|
|
81
|
-
async fetch(
|
|
82
|
-
const encodedRepoName = encodeURIComponent(
|
|
80
|
+
async fetch(resource) {
|
|
81
|
+
const encodedRepoName = encodeURIComponent(resource.appName);
|
|
83
82
|
const provider = await this.abapProvider.get(this.configuration);
|
|
84
83
|
const ui5Repo = provider.getUi5AbapRepository();
|
|
85
84
|
const response = await ui5Repo.get(`/Repositories('${encodedRepoName}')`, {
|
|
@@ -94,7 +93,7 @@ export default class AbapRepository {
|
|
|
94
93
|
const buffer = Buffer.from(data.d.ZipArchive, "base64");
|
|
95
94
|
return unzipZipEntries(buffer);
|
|
96
95
|
}
|
|
97
|
-
throw new Error(`App '${
|
|
96
|
+
throw new Error(`App '${resource.appName}' doesn't contain files`);
|
|
98
97
|
}
|
|
99
98
|
}
|
|
100
99
|
__decorate([
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import { IConfiguration
|
|
1
|
+
import { IConfiguration } from "./../model/types.js";
|
|
2
2
|
import IRepository from "./repository.js";
|
|
3
|
-
import
|
|
3
|
+
import ICachedResource from "../cache/cachedResource.js";
|
|
4
|
+
export interface IHtml5Resource extends ICachedResource {
|
|
5
|
+
appVersion: string;
|
|
6
|
+
appHostId: string;
|
|
7
|
+
}
|
|
4
8
|
export default class HTML5Repository implements IRepository {
|
|
5
9
|
private configuration;
|
|
10
|
+
private validator;
|
|
6
11
|
constructor(configuration: IConfiguration);
|
|
7
|
-
getAppVariantIdHierarchy(
|
|
8
|
-
fetch(
|
|
9
|
-
fetchReuseLib(_libName: string, _cachebusterToken: string, lib: IReuseLibInfo): Promise<Map<string, string>>;
|
|
12
|
+
getAppVariantIdHierarchy(_appId: string): Promise<IHtml5Resource[]>;
|
|
13
|
+
fetch(resource: IHtml5Resource): Promise<Map<string, string>>;
|
|
10
14
|
getMetadata(): Promise<any>;
|
|
11
15
|
private getHtml5RepoInfo;
|
|
12
16
|
private getHTML5Credentials;
|
|
@@ -9,39 +9,30 @@ import RequestUtil from "../util/requestUtil.js";
|
|
|
9
9
|
import { getLogger } from "@ui5/logger";
|
|
10
10
|
import { unzipZipEntries } from "../util/zipUtil.js";
|
|
11
11
|
import { cached } from "../cache/cacheHolder.js";
|
|
12
|
-
import
|
|
12
|
+
import CFValidator from "../util/validator/cfValidator.js";
|
|
13
13
|
const log = getLogger("@ui5/task-adaptation::HTML5Repository");
|
|
14
14
|
export default class HTML5Repository {
|
|
15
15
|
configuration;
|
|
16
|
+
validator = new CFValidator();
|
|
16
17
|
constructor(configuration) {
|
|
17
18
|
this.configuration = configuration;
|
|
18
|
-
validateConfiguration(configuration
|
|
19
|
+
this.validator.validateConfiguration(configuration);
|
|
19
20
|
}
|
|
20
|
-
async getAppVariantIdHierarchy(
|
|
21
|
-
const
|
|
21
|
+
async getAppVariantIdHierarchy(_appId) {
|
|
22
|
+
const { appName, appVersion, appHostId } = this.configuration;
|
|
23
|
+
if (!appName || !appVersion || !appHostId) {
|
|
24
|
+
throw new Error("Missing required configuration properties appName, appVersion or appHostId");
|
|
25
|
+
}
|
|
22
26
|
return [{
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
appName,
|
|
28
|
+
cacheBusterToken: this.getMetadata().then(metadata => metadata.changedOn),
|
|
29
|
+
appVersion,
|
|
30
|
+
appHostId,
|
|
26
31
|
}];
|
|
27
32
|
}
|
|
28
|
-
async fetch(
|
|
33
|
+
async fetch(resource) {
|
|
29
34
|
const { token, baseUri } = await this.getHtml5RepoInfo();
|
|
30
|
-
|
|
31
|
-
appName: this.configuration.appName,
|
|
32
|
-
appVersion: this.configuration.appVersion,
|
|
33
|
-
appHostId: this.configuration.appHostId
|
|
34
|
-
};
|
|
35
|
-
return this.getAppZipEntries(appData, baseUri, token);
|
|
36
|
-
}
|
|
37
|
-
async fetchReuseLib(_libName, _cachebusterToken, lib) {
|
|
38
|
-
const { token, baseUri } = await this.getHtml5RepoInfo();
|
|
39
|
-
const libAppData = {
|
|
40
|
-
appName: lib.html5AppName,
|
|
41
|
-
appVersion: lib.html5AppVersion,
|
|
42
|
-
appHostId: lib.html5AppHostId
|
|
43
|
-
};
|
|
44
|
-
return this.getAppZipEntries(libAppData, baseUri, token);
|
|
35
|
+
return this.getAppZipEntries(resource, baseUri, token);
|
|
45
36
|
}
|
|
46
37
|
async getMetadata() {
|
|
47
38
|
const { token, baseUri } = await this.getHtml5RepoInfo();
|
|
@@ -65,17 +56,17 @@ export default class HTML5Repository {
|
|
|
65
56
|
async getHTML5Credentials(spaceGuid) {
|
|
66
57
|
log.verbose("Getting HTML5 Repo Runtime credentials from space " + spaceGuid);
|
|
67
58
|
const PLAN_NAME = "app-runtime";
|
|
68
|
-
const
|
|
59
|
+
const SERVICE_INSTANCE_NAME = "html5-apps-repo-runtime";
|
|
69
60
|
const getParams = {
|
|
70
61
|
spaceGuids: [spaceGuid],
|
|
71
62
|
planNames: [PLAN_NAME],
|
|
72
|
-
names: [
|
|
63
|
+
names: [SERVICE_INSTANCE_NAME]
|
|
73
64
|
};
|
|
74
65
|
const createParams = {
|
|
75
66
|
spaceGuid,
|
|
76
67
|
planName: PLAN_NAME,
|
|
77
68
|
serviceName: "html5-apps-repo",
|
|
78
|
-
serviceInstanceName:
|
|
69
|
+
serviceInstanceName: SERVICE_INSTANCE_NAME,
|
|
79
70
|
tags: ["html5-apps-repo-rt"]
|
|
80
71
|
};
|
|
81
72
|
const serviceKeys = await CFUtil.getServiceInstanceKeys(getParams, createParams);
|
|
@@ -106,9 +97,10 @@ export default class HTML5Repository {
|
|
|
106
97
|
const metadata = await RequestUtil.get(uri, requestOptions);
|
|
107
98
|
return metadata.find((item) => item.appHostId === appHostId && item.applicationName === appName && item.applicationVersion === appVersion);
|
|
108
99
|
}
|
|
109
|
-
async getAppZipEntries(
|
|
110
|
-
const
|
|
111
|
-
const
|
|
100
|
+
async getAppZipEntries(resource, html5RepoBaseUri, token) {
|
|
101
|
+
const { appName, appVersion, appHostId } = resource;
|
|
102
|
+
const uri = `${html5RepoBaseUri}/applications/content/${appName}-${appVersion}/`;
|
|
103
|
+
const zip = await this.download(token, appHostId, uri);
|
|
112
104
|
return unzipZipEntries(zip);
|
|
113
105
|
}
|
|
114
106
|
async download(token, appHostId, uri) {
|
|
@@ -132,7 +124,4 @@ export default class HTML5Repository {
|
|
|
132
124
|
__decorate([
|
|
133
125
|
cached()
|
|
134
126
|
], HTML5Repository.prototype, "fetch", null);
|
|
135
|
-
__decorate([
|
|
136
|
-
cached()
|
|
137
|
-
], HTML5Repository.prototype, "fetchReuseLib", null);
|
|
138
127
|
//# sourceMappingURL=html5Repository.js.map
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import { IAppVariantIdHierarchyItem } from "../model/appVariantIdHierarchyItem.js";
|
|
2
|
-
import { IConfiguration } from "../model/configuration.js";
|
|
3
|
-
import { IReuseLibInfo } from "../model/types.js";
|
|
4
1
|
import IRepository from "./repository.js";
|
|
2
|
+
import ICachedResource from "../cache/cachedResource.js";
|
|
3
|
+
export interface ILocalResource extends ICachedResource {
|
|
4
|
+
absolutePath: string;
|
|
5
|
+
}
|
|
5
6
|
export default class LocalRepository implements IRepository {
|
|
6
|
-
private configuration;
|
|
7
|
-
constructor(configuration: IConfiguration);
|
|
8
7
|
downloadAnnotationFile(_uri: string): Promise<Map<string, string>>;
|
|
9
|
-
getAppVariantIdHierarchy(appId: string): Promise<
|
|
10
|
-
fetch(
|
|
11
|
-
fetchReuseLib(libName: string, cachebusterToken: string, _lib: IReuseLibInfo): Promise<Map<string, string>>;
|
|
8
|
+
getAppVariantIdHierarchy(appId: string): Promise<ILocalResource[]>;
|
|
9
|
+
fetch(resource: ILocalResource): Promise<Map<string, string>>;
|
|
12
10
|
private collectAppVariantIdHierarchyItems;
|
|
13
11
|
private getExistingManifestPath;
|
|
14
|
-
private readFilesInBaseAppDir;
|
|
15
12
|
private getLocalFilesDirectory;
|
|
16
13
|
}
|
|
@@ -4,10 +4,6 @@ import fs from "node:fs/promises";
|
|
|
4
4
|
import FsUtil from "../util/fsUtil.js";
|
|
5
5
|
const log = getLogger("@ui5/task-adaptation::LocalRepository");
|
|
6
6
|
export default class LocalRepository {
|
|
7
|
-
configuration;
|
|
8
|
-
constructor(configuration) {
|
|
9
|
-
this.configuration = configuration;
|
|
10
|
-
}
|
|
11
7
|
async downloadAnnotationFile(_uri) {
|
|
12
8
|
log.verbose("Downloading annotation files is not supported in LocalRepository.");
|
|
13
9
|
return new Map();
|
|
@@ -17,26 +13,24 @@ export default class LocalRepository {
|
|
|
17
13
|
await this.collectAppVariantIdHierarchyItems(appId, items);
|
|
18
14
|
return items;
|
|
19
15
|
}
|
|
20
|
-
fetch(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
fetchReuseLib(libName, cachebusterToken, _lib) {
|
|
24
|
-
return this.readFilesInBaseAppDir(libName, cachebusterToken);
|
|
16
|
+
fetch(resource) {
|
|
17
|
+
log.verbose(`Fetching base app files from local directory: ${resource.absolutePath}`);
|
|
18
|
+
return FsUtil.readFilesRecursively(resource.absolutePath);
|
|
25
19
|
}
|
|
26
20
|
async collectAppVariantIdHierarchyItems(appId, items) {
|
|
27
21
|
const appDir = this.getLocalFilesDirectory(appId);
|
|
28
22
|
const filenames = [
|
|
29
|
-
["manifest.json"],
|
|
30
|
-
["manifest.appdescr_variant"],
|
|
31
|
-
["
|
|
32
|
-
["
|
|
23
|
+
{ path: ["webapp", "manifest.json"], suffix: "" },
|
|
24
|
+
{ path: ["webapp", "manifest.appdescr_variant"], suffix: "" },
|
|
25
|
+
{ path: ["manifest.json"], suffix: "-opt-static-abap" },
|
|
26
|
+
{ path: ["manifest.appdescr_variant"], suffix: "-opt-static-abap" },
|
|
33
27
|
];
|
|
34
|
-
const filepaths = filenames.map((filename) => path.join(appDir, ...filename));
|
|
28
|
+
const filepaths = filenames.map((filename) => path.join(appDir + filename.suffix, ...filename.path));
|
|
35
29
|
const existingManifestPath = await this.getExistingManifestPath(filepaths);
|
|
36
30
|
items.push({
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
appName: appId,
|
|
32
|
+
cacheBusterToken: Promise.resolve("local"),
|
|
33
|
+
absolutePath: path.dirname(existingManifestPath),
|
|
40
34
|
});
|
|
41
35
|
if (existingManifestPath.endsWith("manifest.appdescr_variant")) {
|
|
42
36
|
const manifestContent = await fs.readFile(existingManifestPath, "utf-8");
|
|
@@ -52,12 +46,8 @@ export default class LocalRepository {
|
|
|
52
46
|
}
|
|
53
47
|
throw new Error(`None of the paths exist: '${filePaths.join("', '")}'.`);
|
|
54
48
|
}
|
|
55
|
-
readFilesInBaseAppDir(_appId, cachebusterToken) {
|
|
56
|
-
log.verbose(`Fetching base app files from local directory: ${cachebusterToken}`);
|
|
57
|
-
return FsUtil.readFilesRecursively(cachebusterToken);
|
|
58
|
-
}
|
|
59
49
|
getLocalFilesDirectory(appId) {
|
|
60
|
-
const adpDirConfigured = process.env.ADP_BUILDER_DIR
|
|
50
|
+
const adpDirConfigured = process.env.ADP_BUILDER_DIR;
|
|
61
51
|
const adpDir = adpDirConfigured
|
|
62
52
|
? path.normalize(adpDirConfigured).replace(/\\/g, "/").replace(/\/+$/, "").split("/")
|
|
63
53
|
: [".."];
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { IReuseLibInfo } from "../model/types.js";
|
|
1
|
+
import ICachedResource from "../cache/cachedResource.js";
|
|
3
2
|
export default interface IRepository {
|
|
4
|
-
getAppVariantIdHierarchy(appId: string): Promise<
|
|
5
|
-
fetch(
|
|
6
|
-
fetchReuseLib(libName: string, cachebusterToken: string, lib: IReuseLibInfo): Promise<Map<string, string>>;
|
|
3
|
+
getAppVariantIdHierarchy(appId: string): Promise<ICachedResource[]>;
|
|
4
|
+
fetch(resource: ICachedResource): Promise<Map<string, string>>;
|
|
7
5
|
downloadAnnotationFile(uri: string): Promise<Map<string, string>>;
|
|
8
6
|
}
|
package/dist/util/filesUtil.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { IChange } from "../model/types.js";
|
|
1
2
|
export default class FilesUtil {
|
|
2
3
|
static filter(files: ReadonlyMap<string, string>): ReadonlyMap<string, string>;
|
|
4
|
+
static sortByTimeStamp(a: IChange, b: IChange): number;
|
|
3
5
|
/**
|
|
4
6
|
* 1p. i18n.properties are not renamed and property keys are ignored during
|
|
5
7
|
* the renaming across the files.
|
package/dist/util/filesUtil.js
CHANGED
|
@@ -23,6 +23,13 @@ export default class FilesUtil {
|
|
|
23
23
|
});
|
|
24
24
|
return result;
|
|
25
25
|
}
|
|
26
|
+
static sortByTimeStamp(a, b) {
|
|
27
|
+
if (a.creation < b.creation)
|
|
28
|
+
return -1;
|
|
29
|
+
if (a.creation > b.creation)
|
|
30
|
+
return 1;
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
26
33
|
/**
|
|
27
34
|
* 1p. i18n.properties are not renamed and property keys are ignored during
|
|
28
35
|
* the renaming across the files.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AbapTarget } from "@sap-ux/system-access";
|
|
2
|
+
import { IAbapTargetMeta, IConfiguration, LandscapeType } from "../../model/configuration.js";
|
|
3
|
+
import IValidator from "./validator.js";
|
|
4
|
+
export default class AbapValidator implements IValidator {
|
|
5
|
+
type: LandscapeType;
|
|
6
|
+
validateAndGetAbapTarget(target: AbapTarget & IAbapTargetMeta | undefined, destination: string | undefined): AbapTarget & IAbapTargetMeta;
|
|
7
|
+
validateConfiguration({ target, destination }: IConfiguration): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { validateObject } from "../commonUtil.js";
|
|
2
|
+
import BtpUtils from "@sap-ux/btp-utils";
|
|
3
|
+
import { getLogger } from "@ui5/logger";
|
|
4
|
+
const log = getLogger("@ui5/task-adaptation::AbapValidator");
|
|
5
|
+
export default class AbapValidator {
|
|
6
|
+
type = "abap";
|
|
7
|
+
validateAndGetAbapTarget(target, destination) {
|
|
8
|
+
if (target) {
|
|
9
|
+
// if target configuration appears, we validate that it should be
|
|
10
|
+
// either target/destination for BAS or target/url for IDE we're
|
|
11
|
+
// trying to detect is it destination for BAS or url for IDE
|
|
12
|
+
const abapTargetProperties = BtpUtils.isAppStudio() ? ["destination"] : ["url"];
|
|
13
|
+
validateObject(target, abapTargetProperties, "should be specified in ui5.yaml configuration/target");
|
|
14
|
+
return target;
|
|
15
|
+
}
|
|
16
|
+
else if (destination) {
|
|
17
|
+
log.warn("Destination is deprecated, use target/destination configuration instead");
|
|
18
|
+
return { destination };
|
|
19
|
+
}
|
|
20
|
+
throw new Error("Target should be specified in ui5.yaml configuration to connect the ABAP system");
|
|
21
|
+
}
|
|
22
|
+
validateConfiguration({ target, destination }) {
|
|
23
|
+
this.validateAndGetAbapTarget(target, destination);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=abapValidator.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { validateConfiguration } from "../commonUtil.js";
|
|
2
|
+
export default class CFValidator {
|
|
3
|
+
type = "cf";
|
|
4
|
+
validateConfiguration(configuration) {
|
|
5
|
+
validateConfiguration(configuration, ["appHostId", "appName", "appVersion"]);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=cfValidator.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { IConfiguration, LandscapeType } from "../../model/configuration.js";
|
|
2
|
+
export default interface IValidator {
|
|
3
|
+
type: LandscapeType;
|
|
4
|
+
validateConfiguration(configuration: IConfiguration): void;
|
|
5
|
+
}
|
|
6
|
+
export declare function isOneOf<T extends readonly unknown[]>(values: T, value: unknown): value is T[number];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ui5/task-adaptation",
|
|
3
|
-
"version": "1.6.5-rc.
|
|
3
|
+
"version": "1.6.5-rc.3",
|
|
4
4
|
"description": "Custom task for ui5-builder which allows building UI5 Flexibility Adaptation Projects for SAP BTP, Cloud Foundry environment",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@sap-ux/axios-extension": "^1.22.9",
|
|
37
37
|
"@sap-ux/btp-utils": "^1.1.3",
|
|
38
|
-
"@sap-ux/store": "^1.
|
|
39
|
-
"@sap-ux/system-access": "^0.
|
|
38
|
+
"@sap-ux/store": "^1.5.13",
|
|
39
|
+
"@sap-ux/system-access": "^0.7.5",
|
|
40
40
|
"@sap/cf-tools": "^3.2.2",
|
|
41
41
|
"@ui5/fs": "^4.0.1",
|
|
42
42
|
"@ui5/logger": "^4.0.1",
|
|
@@ -112,7 +112,8 @@
|
|
|
112
112
|
"src/adapters/adapter.ts",
|
|
113
113
|
"src/adapters/previewAdapter.ts",
|
|
114
114
|
"src/repositories/repository.ts",
|
|
115
|
-
"src/annotations/annotationManager.ts"
|
|
115
|
+
"src/annotations/annotationManager.ts",
|
|
116
|
+
"src/cache/cachedResource.ts"
|
|
116
117
|
],
|
|
117
118
|
"check-coverage": true,
|
|
118
119
|
"statements": 85,
|