@ui5/task-adaptation 1.6.5-rc.2 → 1.6.5-rc.4
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/adapters/abapAdapter.d.ts +7 -5
- package/dist/adapters/abapAdapter.js +9 -11
- package/dist/adapters/adapter.d.ts +9 -5
- package/dist/adapters/adapter.js +20 -0
- package/dist/adapters/cfAdapter.d.ts +8 -5
- package/dist/adapters/cfAdapter.js +16 -10
- package/dist/adapters/commands/command.d.ts +26 -23
- package/dist/adapters/commands/command.js +73 -46
- package/dist/adapters/commands/fetchEndpointsCommand.d.ts +9 -0
- package/dist/adapters/commands/fetchEndpointsCommand.js +21 -0
- package/dist/adapters/commands/fetchPreviewResourcesCommand.d.ts +15 -0
- package/dist/adapters/commands/fetchPreviewResourcesCommand.js +103 -0
- package/dist/adapters/commands/filterFilesCommand.d.ts +4 -0
- package/dist/adapters/commands/filterFilesCommand.js +22 -0
- package/dist/adapters/commands/omitDeletedResourcesCommand.d.ts +10 -0
- package/dist/adapters/commands/omitDeletedResourcesCommand.js +31 -0
- package/dist/adapters/commands/processPreviewResourcesCommand.d.ts +9 -0
- package/dist/adapters/commands/processPreviewResourcesCommand.js +55 -0
- package/dist/adapters/commands/renameFilesCommand.d.ts +20 -0
- package/dist/{util/filesUtil.js → adapters/commands/renameFilesCommand.js} +34 -43
- package/dist/adapters/commands/writeResourcesCommand.d.ts +7 -0
- package/dist/adapters/commands/writeResourcesCommand.js +20 -0
- package/dist/adapters/commands/xsAppJsonEnhanceRoutesCommand.d.ts +3 -3
- package/dist/adapters/commands/xsAppJsonEnhanceRoutesCommand.js +4 -4
- package/dist/adapters/previewAdapter.d.ts +12 -6
- package/dist/adapters/previewAdapter.js +28 -7
- package/dist/annotations/abapAnnotationManager.js +1 -1
- package/dist/annotations/dataSource/dataSourceManager.d.ts +2 -1
- package/dist/annotations/dataSource/dataSourceManager.js +16 -7
- package/dist/{appVariantManager.d.ts → appVariant.d.ts} +2 -9
- package/dist/{appVariantManager.js → appVariant.js} +16 -28
- package/dist/{baseAppManager.js → baseApp.js} +6 -12
- package/dist/bundle.js +53 -12
- package/dist/cache/cacheHolder.d.ts +3 -3
- 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.d.ts +1 -1
- package/dist/index.js +44 -69
- package/dist/landscapeConfiguration.d.ts +2 -2
- package/dist/landscapeConfiguration.js +39 -37
- package/dist/model/configuration.d.ts +1 -4
- package/dist/model/configuration.js +1 -1
- package/dist/model/types.d.ts +9 -2
- package/dist/repositories/abapProvider.js +2 -2
- package/dist/repositories/abapRepository.d.ts +6 -5
- package/dist/repositories/abapRepository.js +10 -11
- package/dist/repositories/html5Repository.d.ts +8 -5
- package/dist/repositories/html5Repository.js +18 -30
- package/dist/repositories/localRepository.d.ts +8 -12
- package/dist/repositories/localRepository.js +53 -43
- package/dist/repositories/repository.d.ts +3 -5
- package/dist/util/cf/xsAppJsonUtil.d.ts +16 -3
- package/dist/util/cf/xsAppJsonUtil.js +7 -18
- package/dist/util/commonUtil.d.ts +6 -0
- package/dist/util/commonUtil.js +17 -0
- package/dist/util/fsUtil.d.ts +2 -3
- package/dist/util/fsUtil.js +12 -33
- package/dist/util/renamingUtil.js +50 -82
- package/dist/util/resourceUtil.d.ts +21 -5
- package/dist/util/resourceUtil.js +52 -11
- package/dist/util/validator/abapConnectionValidator.d.ts +5 -0
- package/dist/util/validator/abapConnectionValidator.js +22 -0
- package/dist/util/validator/abapValidator.d.ts +2 -4
- package/dist/util/validator/abapValidator.js +4 -16
- package/dist/util/validator/validator.d.ts +1 -0
- package/dist/util/validator/validator.js +11 -0
- package/dist/util/workspaceManager.d.ts +9 -0
- package/dist/util/workspaceManager.js +46 -0
- package/dist/util/zipUtil.d.ts +1 -1
- package/dist/util/zipUtil.js +1 -1
- package/package.json +13 -13
- package/.hyperspace/pull_request_bot.json +0 -19
- package/dist/previewManager.d.ts +0 -14
- package/dist/previewManager.js +0 -141
- package/dist/util/filesUtil.d.ts +0 -19
- package/scripts/metadataDownloadHelper.ts +0 -88
- package/scripts/publish.ts +0 -256
- package/scripts/test-integration-prep.sh +0 -4
- /package/dist/{baseAppManager.d.ts → baseApp.d.ts} +0 -0
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
import * as resourceFactory from "@ui5/fs/resourceFactory";
|
|
2
2
|
import { posix as path } from "path";
|
|
3
3
|
const UTF8 = "utf8";
|
|
4
|
+
/**
|
|
5
|
+
* Extensions of files whose contents are processed by the adaptation
|
|
6
|
+
* pipeline as text. Anything outside this whitelist is treated as binary
|
|
7
|
+
* (e.g. images, fonts) and is saved to the workspace verbatim by WorkspaceManager.
|
|
8
|
+
*
|
|
9
|
+
* Kept in sync with EXTENSIONS_TO_PROCESS in appVariant.ts.
|
|
10
|
+
*/
|
|
11
|
+
export const TEXT_EXTENSIONS = new Set([
|
|
12
|
+
"js",
|
|
13
|
+
"json",
|
|
14
|
+
"xml",
|
|
15
|
+
"html",
|
|
16
|
+
"properties",
|
|
17
|
+
"change",
|
|
18
|
+
"appdescr_variant",
|
|
19
|
+
"ctrl_variant",
|
|
20
|
+
"ctrl_variant_change",
|
|
21
|
+
"ctrl_variant_management_change",
|
|
22
|
+
"variant",
|
|
23
|
+
"fioriversion",
|
|
24
|
+
"codeChange",
|
|
25
|
+
"xmlViewChange",
|
|
26
|
+
"context",
|
|
27
|
+
]);
|
|
4
28
|
export default class ResourceUtil {
|
|
5
29
|
static getRootFolder(projectNamespace) {
|
|
6
30
|
const newPath = ["/resources"];
|
|
@@ -21,7 +45,7 @@ export default class ResourceUtil {
|
|
|
21
45
|
* NOTE: to write in project folder (folder where 'webapp',
|
|
22
46
|
* 'package.json', 'ui5.yaml' located), use writeInProject method.
|
|
23
47
|
* @param dir The directory to write files to.
|
|
24
|
-
* @param files A Map of file paths and their contents.
|
|
48
|
+
* @param files A Map of file paths and their contents as Buffer.
|
|
25
49
|
* @returns A promise that resolves when all files have been written.
|
|
26
50
|
*/
|
|
27
51
|
static write(dir, files) {
|
|
@@ -30,8 +54,8 @@ export default class ResourceUtil {
|
|
|
30
54
|
virBasePath: "/"
|
|
31
55
|
});
|
|
32
56
|
const promises = [];
|
|
33
|
-
files.forEach((
|
|
34
|
-
const resource =
|
|
57
|
+
files.forEach((content, filename) => {
|
|
58
|
+
const resource = ResourceUtil.createResourceFromContent("/" + filename, content);
|
|
35
59
|
promises.push(fsTarget.write(resource));
|
|
36
60
|
});
|
|
37
61
|
return Promise.all(promises);
|
|
@@ -40,7 +64,7 @@ export default class ResourceUtil {
|
|
|
40
64
|
* Write files to the project folder (folder where 'webapp',
|
|
41
65
|
* 'package.json', 'ui5.yaml' located), use writeInProject method.
|
|
42
66
|
* @param dir The directory to write files to.
|
|
43
|
-
* @param files A Map of file paths and their contents.
|
|
67
|
+
* @param files A Map of file paths and their contents as Buffer.
|
|
44
68
|
* @returns A promise that resolves when all files have been written.
|
|
45
69
|
*/
|
|
46
70
|
static writeInProject(dir, files) {
|
|
@@ -53,7 +77,7 @@ export default class ResourceUtil {
|
|
|
53
77
|
* @param dir The directory to search in.
|
|
54
78
|
* @param pattern The glob pattern to match files, e.g., "/ui5AppInfo.json".
|
|
55
79
|
* @param excludes An array of glob patterns to exclude from the search.
|
|
56
|
-
* @returns A promise that resolves to a Map of file paths and their contents.
|
|
80
|
+
* @returns A promise that resolves to a Map of file paths and their contents as Buffer.
|
|
57
81
|
*/
|
|
58
82
|
static byGlob(dir, pattern, excludes = []) {
|
|
59
83
|
const adapter = resourceFactory.createAdapter({
|
|
@@ -68,7 +92,7 @@ export default class ResourceUtil {
|
|
|
68
92
|
* 'package.json', 'ui5.yaml' located), excluding specified glob patterns.
|
|
69
93
|
* @param pattern The glob pattern to match files, e.g., "/ui5AppInfo.json".
|
|
70
94
|
* @param excludes An array of glob patterns to exclude from the search.
|
|
71
|
-
* @returns A promise that resolves to a Map of file paths and their contents.
|
|
95
|
+
* @returns A promise that resolves to a Map of file paths and their contents as Buffer.
|
|
72
96
|
*/
|
|
73
97
|
static byGlobInProject(pattern, excludes = []) {
|
|
74
98
|
return ResourceUtil.byGlob("./", pattern, [
|
|
@@ -78,7 +102,7 @@ export default class ResourceUtil {
|
|
|
78
102
|
].concat(excludes));
|
|
79
103
|
}
|
|
80
104
|
static getString(resource) {
|
|
81
|
-
return resource.getBuffer().then((buffer) => buffer.toString(UTF8));
|
|
105
|
+
return resource.getBuffer().then((buffer) => buffer.toString(UTF8).replaceAll("\r\n", "\n"));
|
|
82
106
|
}
|
|
83
107
|
static getJson(resource) {
|
|
84
108
|
return resource.getBuffer().then((buffer) => JSON.parse(buffer.toString(UTF8)));
|
|
@@ -87,10 +111,12 @@ export default class ResourceUtil {
|
|
|
87
111
|
resource.setBuffer(Buffer.from(str, UTF8));
|
|
88
112
|
}
|
|
89
113
|
static createResource(filename, projectNamespace, content) {
|
|
90
|
-
return
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
114
|
+
return ResourceUtil.createResourceFromContent(this.getResourcePath(projectNamespace, filename), content);
|
|
115
|
+
}
|
|
116
|
+
static createResourceFromContent(resourcePath, content) {
|
|
117
|
+
return resourceFactory.createResource(Buffer.isBuffer(content)
|
|
118
|
+
? { path: resourcePath, buffer: content }
|
|
119
|
+
: { path: resourcePath, string: content });
|
|
94
120
|
}
|
|
95
121
|
static async toFileMap(resources, projectNamespace) {
|
|
96
122
|
const files = new Map();
|
|
@@ -100,5 +126,20 @@ export default class ResourceUtil {
|
|
|
100
126
|
}
|
|
101
127
|
return files;
|
|
102
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Decodes the text-extension files of a buffer map to UTF-8 strings.
|
|
131
|
+
* Binary files (e.g. images, fonts) are dropped — they are expected to
|
|
132
|
+
* have been written to the workspace separately and are not relevant
|
|
133
|
+
* to the in-memory text pipeline.
|
|
134
|
+
*/
|
|
135
|
+
static toTextMap(buffers) {
|
|
136
|
+
const text = new Map();
|
|
137
|
+
buffers.forEach((buffer, filename) => {
|
|
138
|
+
if (TEXT_EXTENSIONS.has(path.extname(filename).slice(1))) {
|
|
139
|
+
text.set(filename, buffer.toString(UTF8));
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
return text;
|
|
143
|
+
}
|
|
103
144
|
}
|
|
104
145
|
//# sourceMappingURL=resourceUtil.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { AbapTarget } from "@sap-ux/system-access";
|
|
2
|
+
import { IAbapTargetMeta } from "../../model/configuration.js";
|
|
3
|
+
export default class AbapConnectionValidator {
|
|
4
|
+
validateAndGetAbapTarget(target: AbapTarget & IAbapTargetMeta | undefined, destination: string | undefined): AbapTarget & IAbapTargetMeta;
|
|
5
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { validateObject } from "../commonUtil.js";
|
|
2
|
+
import { isAppStudio } from "@sap-ux/btp-utils";
|
|
3
|
+
import { getLogger } from "@ui5/logger";
|
|
4
|
+
const log = getLogger("@ui5/task-adaptation::AbapConnectionValidator");
|
|
5
|
+
export default class AbapConnectionValidator {
|
|
6
|
+
validateAndGetAbapTarget(target, destination) {
|
|
7
|
+
if (target) {
|
|
8
|
+
// if target configuration appears, we validate that it should be
|
|
9
|
+
// either target/destination for BAS or target/url for IDE we're
|
|
10
|
+
// trying to detect is it destination for BAS or url for IDE
|
|
11
|
+
const abapTargetProperties = isAppStudio() ? ["destination"] : ["url"];
|
|
12
|
+
validateObject(target, abapTargetProperties, "should be specified in ui5.yaml configuration/target");
|
|
13
|
+
return target;
|
|
14
|
+
}
|
|
15
|
+
else if (destination) {
|
|
16
|
+
log.warn("Destination is deprecated, use target/destination configuration instead");
|
|
17
|
+
return { destination };
|
|
18
|
+
}
|
|
19
|
+
throw new Error("Target should be specified in ui5.yaml configuration to connect the ABAP system");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=abapConnectionValidator.js.map
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { IAbapTargetMeta, IConfiguration, LandscapeType } from "../../model/configuration.js";
|
|
1
|
+
import { IConfiguration, LandscapeType } from "../../model/configuration.js";
|
|
3
2
|
import IValidator from "./validator.js";
|
|
4
3
|
export default class AbapValidator implements IValidator {
|
|
5
4
|
type: LandscapeType;
|
|
6
|
-
|
|
7
|
-
validateConfiguration({ target, destination }: IConfiguration): void;
|
|
5
|
+
validateConfiguration({ destination, target }: IConfiguration): void;
|
|
8
6
|
}
|
|
@@ -1,26 +1,14 @@
|
|
|
1
|
-
import { validateObject } from "../commonUtil.js";
|
|
2
|
-
import BtpUtils from "@sap-ux/btp-utils";
|
|
3
1
|
import { getLogger } from "@ui5/logger";
|
|
4
2
|
const log = getLogger("@ui5/task-adaptation::AbapValidator");
|
|
5
3
|
export default class AbapValidator {
|
|
6
4
|
type = "abap";
|
|
7
|
-
|
|
8
|
-
if (target) {
|
|
9
|
-
|
|
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;
|
|
5
|
+
validateConfiguration({ destination, target }) {
|
|
6
|
+
if (!destination && !target) {
|
|
7
|
+
throw new Error("'target' should be specified in ui5.yaml configuration");
|
|
15
8
|
}
|
|
16
|
-
else if (destination) {
|
|
9
|
+
else if (destination && !target) {
|
|
17
10
|
log.warn("Destination is deprecated, use target/destination configuration instead");
|
|
18
|
-
return { destination };
|
|
19
11
|
}
|
|
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
12
|
}
|
|
25
13
|
}
|
|
26
14
|
//# sourceMappingURL=abapValidator.js.map
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
export function isOneOf(values, value) {
|
|
2
2
|
return values.includes(value);
|
|
3
3
|
}
|
|
4
|
+
export function validateAppId(id) {
|
|
5
|
+
if (!id) {
|
|
6
|
+
throw new Error(`The application id must not be empty.`);
|
|
7
|
+
}
|
|
8
|
+
// 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
|
|
9
|
+
// In the manifest.json file, make sure that the attribute
|
|
10
|
+
// sap.app/id has at least 2 segments.
|
|
11
|
+
if (id.split(".").filter(Boolean).length < 2) {
|
|
12
|
+
throw new Error(`The application id '${id}' must have at least two parts, separated by a period.`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
4
15
|
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default class WorkspaceManager {
|
|
2
|
+
private readonly workspace;
|
|
3
|
+
private readonly projectNamespace;
|
|
4
|
+
private snapshot;
|
|
5
|
+
constructor(workspace: IWorkspace, projectNamespace: string);
|
|
6
|
+
createSnapshot(): Promise<void>;
|
|
7
|
+
restoreSnapshot(): Promise<void>;
|
|
8
|
+
saveAndConvert(buffersPromise: Promise<ReadonlyMap<string, Buffer>>): Promise<ReadonlyMap<string, string>>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import ResourceUtil, { TEXT_EXTENSIONS } from "./resourceUtil.js";
|
|
2
|
+
import { posix as path } from "path";
|
|
3
|
+
const UTF8 = "utf8";
|
|
4
|
+
export default class WorkspaceManager {
|
|
5
|
+
workspace;
|
|
6
|
+
projectNamespace;
|
|
7
|
+
snapshot;
|
|
8
|
+
constructor(workspace, projectNamespace) {
|
|
9
|
+
this.workspace = workspace;
|
|
10
|
+
this.projectNamespace = projectNamespace;
|
|
11
|
+
}
|
|
12
|
+
async createSnapshot() {
|
|
13
|
+
const resources = await this.workspace.byGlob("/**/*");
|
|
14
|
+
const rootFolderLength = ResourceUtil.getRootFolder(this.projectNamespace).length;
|
|
15
|
+
const entries = await Promise.all(resources.map(async (resource) => {
|
|
16
|
+
const filename = resource.getPath().substring(rootFolderLength + 1);
|
|
17
|
+
return [filename, await resource.getBuffer()];
|
|
18
|
+
}));
|
|
19
|
+
this.snapshot = new Map(entries);
|
|
20
|
+
}
|
|
21
|
+
async restoreSnapshot() {
|
|
22
|
+
if (!this.snapshot) {
|
|
23
|
+
throw new Error("No snapshot to restore — call createSnapshot() first");
|
|
24
|
+
}
|
|
25
|
+
const writes = [];
|
|
26
|
+
this.snapshot.forEach((buffer, filename) => {
|
|
27
|
+
const resource = ResourceUtil.createResource(filename, this.projectNamespace, buffer);
|
|
28
|
+
writes.push(this.workspace.write(resource));
|
|
29
|
+
});
|
|
30
|
+
await Promise.all(writes);
|
|
31
|
+
}
|
|
32
|
+
async saveAndConvert(buffersPromise) {
|
|
33
|
+
const buffers = await buffersPromise;
|
|
34
|
+
const writes = [];
|
|
35
|
+
const text = new Map();
|
|
36
|
+
buffers.forEach((buffer, filename) => {
|
|
37
|
+
if (TEXT_EXTENSIONS.has(path.extname(filename).slice(1))) {
|
|
38
|
+
text.set(filename, buffer.toString(UTF8));
|
|
39
|
+
}
|
|
40
|
+
writes.push(this.workspace.write(ResourceUtil.createResource(filename, this.projectNamespace, buffer)));
|
|
41
|
+
});
|
|
42
|
+
await Promise.all(writes);
|
|
43
|
+
return text;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=workspaceManager.js.map
|
package/dist/util/zipUtil.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function unzipZipEntries(zip: Buffer): Promise<Map<string,
|
|
1
|
+
export declare function unzipZipEntries(zip: Buffer): Promise<Map<string, Buffer>>;
|
package/dist/util/zipUtil.js
CHANGED
|
@@ -11,6 +11,6 @@ export async function unzipZipEntries(zip) {
|
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
function mapEntries(entries) {
|
|
14
|
-
return new Map(entries.filter(entry => !entry.isDirectory).map(entry => [entry.entryName, entry.getData()
|
|
14
|
+
return new Map(entries.filter(entry => !entry.isDirectory).map(entry => [entry.entryName, entry.getData()]));
|
|
15
15
|
}
|
|
16
16
|
//# sourceMappingURL=zipUtil.js.map
|
package/package.json
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ui5/task-adaptation",
|
|
3
|
-
"version": "1.6.5-rc.
|
|
3
|
+
"version": "1.6.5-rc.4",
|
|
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": {
|
|
7
7
|
"test": "npm run lint && npm run build && npm run coverage",
|
|
8
8
|
"lint": "eslint ./src ./test/lib",
|
|
9
|
-
"dev": "
|
|
10
|
-
"perf": "
|
|
9
|
+
"dev": "mocha --no-timeouts --no-warnings --import=tsx \"test/lib/**/*.spec.ts\"",
|
|
10
|
+
"perf": "mocha --no-timeouts --no-warnings --import=tsx \"test/lib/**/*.perf.ts\"",
|
|
11
11
|
"coverage": "c8 npm run dev",
|
|
12
12
|
"preversion": "npm test",
|
|
13
13
|
"version": "git-chglog --next-tag v$npm_package_version -o CHANGELOG.md && git add CHANGELOG.md",
|
|
14
14
|
"prepublishOnly": "git push --follow-tags",
|
|
15
15
|
"release-note": "git-chglog -c .chglog/release-config.yml v$npm_package_version",
|
|
16
16
|
"rollup": "tsx rollup/rollup.ts",
|
|
17
|
-
"build": "npm run rollup && tsc -p ./"
|
|
18
|
-
"download-metadata": "tsx scripts/metadataDownloadHelper.ts"
|
|
17
|
+
"build": "npm run rollup && tsc -p ./"
|
|
19
18
|
},
|
|
20
19
|
"repository": {
|
|
21
20
|
"type": "git",
|
|
@@ -33,10 +32,10 @@
|
|
|
33
32
|
"author": "SAP SE",
|
|
34
33
|
"license": "Apache-2.0",
|
|
35
34
|
"dependencies": {
|
|
36
|
-
"@sap-ux/axios-extension": "^
|
|
37
|
-
"@sap-ux/btp-utils": "^
|
|
38
|
-
"@sap-ux/store": "^
|
|
39
|
-
"@sap-ux/system-access": "^0.
|
|
35
|
+
"@sap-ux/axios-extension": "^2.0.1",
|
|
36
|
+
"@sap-ux/btp-utils": "^2.0.1",
|
|
37
|
+
"@sap-ux/store": "^2.0.1",
|
|
38
|
+
"@sap-ux/system-access": "^1.0.1",
|
|
40
39
|
"@sap/cf-tools": "^3.2.2",
|
|
41
40
|
"@ui5/fs": "^4.0.1",
|
|
42
41
|
"@ui5/logger": "^4.0.1",
|
|
@@ -45,6 +44,7 @@
|
|
|
45
44
|
"crc": "^4.3.2",
|
|
46
45
|
"dotenv": "^16.0.3",
|
|
47
46
|
"filenamify": "^6.0.0",
|
|
47
|
+
"glob": "^13.0.0",
|
|
48
48
|
"jsdom": "^23.0.1",
|
|
49
49
|
"transliteration": "^2.3.5",
|
|
50
50
|
"xml-js": "^1.6.11"
|
|
@@ -73,17 +73,16 @@
|
|
|
73
73
|
"eslint": "^9.22.0",
|
|
74
74
|
"eslint-plugin-import": "^2.31.0",
|
|
75
75
|
"esmock": "^2.7.3",
|
|
76
|
-
"glob": "^13.0.0",
|
|
77
76
|
"js-yaml": "^4.1.0",
|
|
78
77
|
"meriyah": "^6.0.3",
|
|
79
78
|
"minimatch": "^9.0.3",
|
|
80
|
-
"mocha": "^11.7.
|
|
79
|
+
"mocha": "^11.7.6",
|
|
81
80
|
"mock-require": "^3.0.3",
|
|
82
81
|
"rollup": "^4.24.0",
|
|
83
82
|
"semver": "^7.3.5",
|
|
84
83
|
"sinon": "^18.0.1",
|
|
85
84
|
"source-map-support": "^0.5.19",
|
|
86
|
-
"tsx": "
|
|
85
|
+
"tsx": "4.21.0",
|
|
87
86
|
"typescript": "^6.0.2",
|
|
88
87
|
"typescript-eslint": "^8.58.0",
|
|
89
88
|
"yargs": "^17.7.2"
|
|
@@ -112,7 +111,8 @@
|
|
|
112
111
|
"src/adapters/adapter.ts",
|
|
113
112
|
"src/adapters/previewAdapter.ts",
|
|
114
113
|
"src/repositories/repository.ts",
|
|
115
|
-
"src/annotations/annotationManager.ts"
|
|
114
|
+
"src/annotations/annotationManager.ts",
|
|
115
|
+
"src/cache/cachedResource.ts"
|
|
116
116
|
],
|
|
117
117
|
"check-coverage": true,
|
|
118
118
|
"statements": 85,
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://devops-insights-pr-bot.cfapps.eu10-004.hana.ondemand.com/schema/pull_request_bot.json",
|
|
3
|
-
"features": {
|
|
4
|
-
"control_panel": false,
|
|
5
|
-
"summarize": {
|
|
6
|
-
"auto_generate_summary": true,
|
|
7
|
-
"auto_insert_summary": true,
|
|
8
|
-
"auto_run_on_draft_pr": true,
|
|
9
|
-
"use_custom_summarize_prompt": false,
|
|
10
|
-
"use_custom_summarize_output_template": false,
|
|
11
|
-
"use_tabular_summarize_output_template": false
|
|
12
|
-
},
|
|
13
|
-
"review": {
|
|
14
|
-
"auto_generate_review": true,
|
|
15
|
-
"auto_run_on_draft_pr": true,
|
|
16
|
-
"use_custom_review_focus": false
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
package/dist/previewManager.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { IConfiguration } from "./model/types.js";
|
|
2
|
-
import IRepository from "./repositories/repository.js";
|
|
3
|
-
export default class PreviewManager {
|
|
4
|
-
private readonly fetchLibsPromises;
|
|
5
|
-
private readonly configuration;
|
|
6
|
-
static createFromRoot(appId: string, repository: IRepository, configuration: IConfiguration): Promise<PreviewManager>;
|
|
7
|
-
static isPreviewRequested(): boolean;
|
|
8
|
-
private constructor();
|
|
9
|
-
processPreviewResources(baseAppFiles: ReadonlyMap<string, string>): Promise<void>;
|
|
10
|
-
private preReadLibs;
|
|
11
|
-
private searchBaseAppXsAppJsonFile;
|
|
12
|
-
private static moveLibraryFiles;
|
|
13
|
-
private static modifyRoutes;
|
|
14
|
-
}
|
package/dist/previewManager.js
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import { getLogger } from "@ui5/logger";
|
|
2
|
-
import ResourceUtil from "./util/resourceUtil.js";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import { fetchCredentialsAndEnhanceRoutes, merge } from "./util/cf/xsAppJsonUtil.js";
|
|
5
|
-
import FsUtil from "./util/fsUtil.js";
|
|
6
|
-
const log = getLogger("@ui5/task-adaptation::PreviewManager");
|
|
7
|
-
const REUSE_DIR = ".adp/reuse";
|
|
8
|
-
const APP_INFO_FILE = "ui5AppInfo.json";
|
|
9
|
-
const XS_APP_JSON_FILE = "xs-app.json";
|
|
10
|
-
export default class PreviewManager {
|
|
11
|
-
fetchLibsPromises = new Map();
|
|
12
|
-
configuration;
|
|
13
|
-
static async createFromRoot(appId, repository, configuration) {
|
|
14
|
-
let ui5AppInfo = "";
|
|
15
|
-
if (PreviewManager.isPreviewRequested()) {
|
|
16
|
-
try {
|
|
17
|
-
ui5AppInfo = await FsUtil.readInProject(APP_INFO_FILE);
|
|
18
|
-
}
|
|
19
|
-
catch (error) {
|
|
20
|
-
throw new Error(`ui5AppInfo.json is missing in project root, cannot process preview resources: ${error instanceof Error ? error.message : String(error)}`);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
log.verbose("Preview mode not requested (env variable ADP_BUILDER_MODE=preview is not set), skipping preview resources processing.");
|
|
25
|
-
}
|
|
26
|
-
return new PreviewManager(appId, ui5AppInfo, repository, configuration);
|
|
27
|
-
}
|
|
28
|
-
static isPreviewRequested() {
|
|
29
|
-
return process.env.ADP_BUILDER_MODE === "preview";
|
|
30
|
-
}
|
|
31
|
-
constructor(appId, ui5AppInfo, repository, configuration) {
|
|
32
|
-
this.configuration = configuration;
|
|
33
|
-
// If no ui5AppInfo is provided, no preview processing is needed
|
|
34
|
-
if (!ui5AppInfo) {
|
|
35
|
-
log.verbose("No ui5AppInfo provided, skipping preview resources processing.");
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
const appInfo = JSON.parse(ui5AppInfo)[appId];
|
|
39
|
-
if (!appInfo) {
|
|
40
|
-
throw new Error(`No app info found for original app id '${appId}' in ui5AppInfo.json`);
|
|
41
|
-
}
|
|
42
|
-
const reuseLibs = appInfo.asyncHints.libs.filter(lib => lib.html5AppHostId && lib.html5AppName && lib.html5AppVersion);
|
|
43
|
-
if (reuseLibs.length > 0) {
|
|
44
|
-
this.fetchLibsPromises = this.preReadLibs(reuseLibs, repository);
|
|
45
|
-
}
|
|
46
|
-
const logMap = {
|
|
47
|
-
Error: log.error,
|
|
48
|
-
Warning: log.warning,
|
|
49
|
-
Info: log.info,
|
|
50
|
-
debug: log.verbose
|
|
51
|
-
};
|
|
52
|
-
appInfo.messages.forEach((message) => {
|
|
53
|
-
const logger = logMap[message.severity] || log.info;
|
|
54
|
-
logger(`ui5AppInfo.json: ${message.severity} Message: ${message.message} (Error Code: ${message.errorCode})`);
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
async processPreviewResources(baseAppFiles) {
|
|
58
|
-
if (!PreviewManager.isPreviewRequested()) {
|
|
59
|
-
log.verbose("Preview mode not requested, skipping downloading reuse libraries and xs-app.json processing.");
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
log.verbose(`Downloading reuse libraries to reuse folder`);
|
|
63
|
-
const xsAppFiles = new Array();
|
|
64
|
-
if (this.fetchLibsPromises.size === 0) {
|
|
65
|
-
log.verbose("No reuse libraries defined in ui5AppInfo.json for preview");
|
|
66
|
-
}
|
|
67
|
-
const mergedFiles = new Map();
|
|
68
|
-
for (const [libName, libFilesPromise] of this.fetchLibsPromises) {
|
|
69
|
-
const libFiles = await libFilesPromise;
|
|
70
|
-
if (!libFiles || libFiles.size === 0) {
|
|
71
|
-
log.warn(`No files found in reuse library ${libName} for preview`);
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
for (const [filename, content] of libFiles) {
|
|
75
|
-
mergedFiles.set(filename, content);
|
|
76
|
-
if (filename.includes(XS_APP_JSON_FILE)) {
|
|
77
|
-
xsAppFiles.push(content);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
this.searchBaseAppXsAppJsonFile(xsAppFiles, baseAppFiles);
|
|
82
|
-
let xsAppJson = merge(xsAppFiles);
|
|
83
|
-
if (xsAppJson) {
|
|
84
|
-
xsAppJson = await fetchCredentialsAndEnhanceRoutes(xsAppJson, this.configuration);
|
|
85
|
-
mergedFiles.set(XS_APP_JSON_FILE, xsAppJson);
|
|
86
|
-
}
|
|
87
|
-
if (mergedFiles.size === 0) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
await ResourceUtil.writeInProject(REUSE_DIR, mergedFiles);
|
|
91
|
-
}
|
|
92
|
-
preReadLibs(reuseLibs, repository) {
|
|
93
|
-
const promises = new Map();
|
|
94
|
-
reuseLibs.forEach(lib => {
|
|
95
|
-
log.info(`Downloading reuse library '${lib.html5AppName}' version '${lib.html5AppVersion}'`);
|
|
96
|
-
const promise = repository
|
|
97
|
-
.fetchReuseLib(lib.html5AppName, lib.html5CacheBusterToken, lib)
|
|
98
|
-
.then((libFiles) => PreviewManager.moveLibraryFiles(libFiles, lib.html5AppName, lib.name));
|
|
99
|
-
promises.set(lib.html5AppName, promise);
|
|
100
|
-
});
|
|
101
|
-
return promises;
|
|
102
|
-
}
|
|
103
|
-
searchBaseAppXsAppJsonFile(xsAppFiles, baseAppFiles) {
|
|
104
|
-
const xsAppJsonContent = baseAppFiles.get(XS_APP_JSON_FILE);
|
|
105
|
-
if (xsAppJsonContent) {
|
|
106
|
-
xsAppFiles.push(xsAppJsonContent);
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
log.warn("xs-app.json is missing in the downloaded base app files for preview");
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
static moveLibraryFiles(inputFiles, libraryName, libId) {
|
|
113
|
-
const files = new Map();
|
|
114
|
-
inputFiles.forEach((content, filename) => {
|
|
115
|
-
const newFilename = path.join(libraryName, filename);
|
|
116
|
-
// Source path in xs-app.json needs to be adjusted to new location
|
|
117
|
-
if (filename.includes(XS_APP_JSON_FILE)) {
|
|
118
|
-
content = PreviewManager.modifyRoutes(content, libraryName, libId);
|
|
119
|
-
}
|
|
120
|
-
files.set(newFilename, content);
|
|
121
|
-
});
|
|
122
|
-
return files;
|
|
123
|
-
}
|
|
124
|
-
;
|
|
125
|
-
static modifyRoutes(xsAppJson, libName, libId) {
|
|
126
|
-
const xsApp = JSON.parse(xsAppJson);
|
|
127
|
-
xsApp.routes = xsApp.routes.map((route) => {
|
|
128
|
-
route.source = route.source.replace(new RegExp("^\\^\\/?(resources/)?"), `^/resources/${libId.replaceAll(".", "/")}/`);
|
|
129
|
-
if (route.service === "html5-apps-repo-rt") {
|
|
130
|
-
route = {
|
|
131
|
-
source: route.source,
|
|
132
|
-
target: route.target,
|
|
133
|
-
localDir: path.join(REUSE_DIR, libName)
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
return route;
|
|
137
|
-
});
|
|
138
|
-
return JSON.stringify(xsApp);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
//# sourceMappingURL=previewManager.js.map
|
package/dist/util/filesUtil.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { IChange } from "../model/types.js";
|
|
2
|
-
export default class FilesUtil {
|
|
3
|
-
static filter(files: ReadonlyMap<string, string>): ReadonlyMap<string, string>;
|
|
4
|
-
static sortByTimeStamp(a: IChange, b: IChange): number;
|
|
5
|
-
/**
|
|
6
|
-
* 1p. i18n.properties are not renamed and property keys are ignored during
|
|
7
|
-
* the renaming across the files.
|
|
8
|
-
* @param files - all files both base and appVariants
|
|
9
|
-
* @param references - Reference maps of the app variant
|
|
10
|
-
* @returns A map of renamed files
|
|
11
|
-
*/
|
|
12
|
-
static rename(files: ReadonlyMap<string, string>, references: Map<string, string>): ReadonlyMap<string, string>;
|
|
13
|
-
private static getManifestSAPUI5DependencyIds;
|
|
14
|
-
private static getI18nPropertyKeys;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* We might rename appVariantIdHierarchy and dependencies, so we restore them after the renaming.
|
|
18
|
-
*/
|
|
19
|
-
export declare function restoreWhatShouldntBeRenamed(): (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => void;
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import * as dotenv from "dotenv";
|
|
2
|
-
import * as fs from "fs/promises";
|
|
3
|
-
|
|
4
|
-
import { Agent } from "https";
|
|
5
|
-
import RequestUtil from "../src/util/requestUtil.js";
|
|
6
|
-
|
|
7
|
-
dotenv.config();
|
|
8
|
-
const httpsAgent = new Agent({ rejectUnauthorized: false });
|
|
9
|
-
|
|
10
|
-
export default class MetadataDownloadHelper {
|
|
11
|
-
|
|
12
|
-
static async readAllUrls() {
|
|
13
|
-
await fs.readdir("./test/resources/annotations/inline", { encoding: "utf8" });
|
|
14
|
-
const resultsObject = JSON.parse(await fs.readFile("./test/resources/allReleasedODataServices.json", { encoding: "utf8" }));
|
|
15
|
-
return this.exractUrlsFromResponse(resultsObject);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
static async fetchAllUrls(host: string) {
|
|
19
|
-
const REQUEST_OPTIONS_JSON = {
|
|
20
|
-
headers: {
|
|
21
|
-
"Content-Type": "application/json; charset=utf-8",
|
|
22
|
-
'Cookie': process.env.cookie,
|
|
23
|
-
},
|
|
24
|
-
httpsAgent
|
|
25
|
-
};
|
|
26
|
-
const url = "/sap/bc/ui2/app_index?sap.fiori/cloudDevAdaptationStatus=released&fields=sap.app/id,sap.app/dataSources/OData/uri";
|
|
27
|
-
const response = await RequestUtil.get(host + url, REQUEST_OPTIONS_JSON);
|
|
28
|
-
const allUris = this.exractUrlsFromResponse(response);
|
|
29
|
-
for (const [index, url] of allUris.entries()) {
|
|
30
|
-
try {
|
|
31
|
-
const metadataFile = await this.fetchMetadataFileByUri(host, url);
|
|
32
|
-
if (typeof metadataFile === "object") {
|
|
33
|
-
console.error(`Received object instead of xml file with content: ${JSON.stringify(metadataFile)}`)
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
// @ts-ignore
|
|
37
|
-
await fs.writeFile(`test/resources/metadata/download/${index}__${url.replaceAll("/", "_")}.xml`, metadataFile, { encoding: "utf8" });
|
|
38
|
-
} catch (e: any) {
|
|
39
|
-
console.error(`Error fetching metadata file with url ${url} with error \n\n ${e}`);
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
private static exractUrlsFromResponse(resultsObject: any) {
|
|
46
|
-
let allUrls: string[] = [];
|
|
47
|
-
resultsObject.results.map((value: any) => {
|
|
48
|
-
allUrls = allUrls.concat(value["sap.app/dataSources/OData/uri"]);
|
|
49
|
-
});
|
|
50
|
-
return allUrls;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
static readMetadataFileByFilePath(filePath: string) {
|
|
54
|
-
return fs.readFile(filePath, { encoding: "utf8" });
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
static fetchMetadataFileByUri(host: string, url: string) {
|
|
58
|
-
const REQUEST_OPTIONS_XML = {
|
|
59
|
-
headers: {
|
|
60
|
-
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
|
|
61
|
-
'Cookie': process.env.cookie,
|
|
62
|
-
},
|
|
63
|
-
httpsAgent,
|
|
64
|
-
timeout: 4000
|
|
65
|
-
};
|
|
66
|
-
url = url.endsWith("/") ? `${url}$metadata` : `${url}/$metadata`;
|
|
67
|
-
return RequestUtil.get(host + url, REQUEST_OPTIONS_XML);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Get the command line arguments
|
|
72
|
-
const args = process.argv;
|
|
73
|
-
|
|
74
|
-
// Find the index of the `--host=` argument
|
|
75
|
-
const hostArgIndex = args.findIndex(arg => arg.startsWith('--host='));
|
|
76
|
-
|
|
77
|
-
// If the `--host=` argument is found
|
|
78
|
-
if (hostArgIndex !== -1) {
|
|
79
|
-
// Extract the value of the `--host=` argument
|
|
80
|
-
const hostArg = args[hostArgIndex];
|
|
81
|
-
let host = hostArg.split('=')[1];
|
|
82
|
-
host = host.endsWith("/") ? host.substring(0, host.lastIndexOf("/")) : host;
|
|
83
|
-
|
|
84
|
-
// Use the `host` variable as needed
|
|
85
|
-
MetadataDownloadHelper.fetchAllUrls(host);
|
|
86
|
-
} else {
|
|
87
|
-
console.info("Please provide missing host parameter");
|
|
88
|
-
}
|