@ui5/task-adaptation 1.6.0 → 1.6.1
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 +28 -9
- package/dist/adapters/abapAdapter.d.ts +14 -0
- package/dist/adapters/abapAdapter.js +45 -0
- package/dist/adapters/adapter.d.ts +8 -0
- package/dist/adapters/adapter.js +2 -0
- package/dist/adapters/cfAdapter.d.ts +12 -0
- package/dist/adapters/cfAdapter.js +46 -0
- package/dist/adapters/commands/addAppVariantIdHierarchyCommand.d.ts +7 -0
- package/dist/adapters/commands/addAppVariantIdHierarchyCommand.js +17 -0
- package/dist/adapters/commands/applyDescriptorChangesCommand.d.ts +10 -0
- package/dist/adapters/commands/applyDescriptorChangesCommand.js +43 -0
- package/dist/adapters/commands/command.d.ts +84 -0
- package/dist/adapters/commands/command.js +108 -0
- package/dist/adapters/commands/downloadAnnotationsCommand.d.ts +12 -0
- package/dist/adapters/commands/downloadAnnotationsCommand.js +26 -0
- package/dist/{util/i18nMerger.d.ts → adapters/commands/i18nPropertiesMergeCommand.d.ts} +13 -10
- package/dist/{util/i18nMerger.js → adapters/commands/i18nPropertiesMergeCommand.js} +30 -27
- package/dist/adapters/commands/setAppVariantIdCommand.d.ts +7 -0
- package/dist/adapters/commands/setAppVariantIdCommand.js +15 -0
- package/dist/adapters/commands/updateCloudDevAdaptationCommand.d.ts +4 -0
- package/dist/adapters/commands/updateCloudDevAdaptationCommand.js +11 -0
- package/dist/adapters/commands/updateCloudPlatformCommand.d.ts +6 -0
- package/dist/adapters/commands/updateCloudPlatformCommand.js +23 -0
- package/dist/adapters/commands/updateComponentNameCommand.d.ts +6 -0
- package/dist/adapters/commands/updateComponentNameCommand.js +13 -0
- package/dist/adapters/commands/xsAppJsonEnhanceRoutesCommand.d.ts +7 -0
- package/dist/adapters/commands/xsAppJsonEnhanceRoutesCommand.js +36 -0
- package/dist/adapters/commands/xsAppJsonMergeCommand.d.ts +5 -0
- package/dist/adapters/commands/xsAppJsonMergeCommand.js +17 -0
- package/dist/adapters/previewAdapter.d.ts +6 -0
- package/dist/adapters/previewAdapter.js +8 -0
- package/dist/appVariantManager.js +3 -0
- package/dist/baseAppManager.d.ts +0 -8
- package/dist/baseAppManager.js +3 -69
- package/dist/bundle.js +37 -35
- package/dist/cache/cacheHolder.js +9 -4
- package/dist/index.js +7 -3
- package/dist/model/appVariantIdHierarchyItem.d.ts +6 -1
- package/dist/model/types.d.ts +6 -0
- package/dist/previewManager.js +16 -23
- package/dist/processors/abapProcessor.d.ts +3 -7
- package/dist/processors/abapProcessor.js +4 -15
- package/dist/processors/cfProcessor.d.ts +5 -11
- package/dist/processors/cfProcessor.js +4 -90
- package/dist/processors/previewProcessor.d.ts +8 -0
- package/dist/processors/previewProcessor.js +11 -0
- package/dist/processors/processor.d.ts +3 -3
- package/dist/processors/processor.js +9 -0
- package/dist/repositories/abapRepoManager.d.ts +1 -1
- package/dist/repositories/html5RepoManager.js +6 -0
- package/dist/util/cf/xsAppJsonUtil.d.ts +13 -0
- package/dist/util/cf/xsAppJsonUtil.js +81 -0
- package/dist/util/cfUtil.d.ts +3 -3
- package/dist/util/cfUtil.js +1 -1
- package/dist/util/filesUtil.d.ts +3 -2
- package/dist/util/filesUtil.js +20 -4
- package/dist/util/fsUtil.d.ts +9 -0
- package/dist/util/fsUtil.js +40 -0
- package/dist/util/movingHandler/changeFileMoveHandler.js +2 -3
- package/dist/util/objectPath.d.ts +19 -0
- package/dist/util/objectPath.js +62 -0
- package/dist/util/renamingHandlers/jsonRenamingHandler.d.ts +12 -0
- package/dist/util/renamingHandlers/jsonRenamingHandler.js +34 -0
- package/dist/util/renamingHandlers/manifestRenamingHandler.d.ts +4 -5
- package/dist/util/renamingHandlers/manifestRenamingHandler.js +7 -18
- package/dist/util/requestUtil.d.ts +1 -1
- package/dist/util/requestUtil.js +5 -2
- package/dist/util/resourceUtil.d.ts +0 -7
- package/dist/util/resourceUtil.js +0 -36
- package/package.json +3 -2
- package/dist/util/movingHandler/fileMoveHandler.d.ts +0 -8
- package/dist/util/movingHandler/fileMoveHandler.js +0 -77
- package/scripts/publish.ts +0 -256
- package/scripts/test-integration-prep.sh +0 -4
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
import AbapRepoManager from "../repositories/abapRepoManager.js";
|
|
2
2
|
import AnnotationManager from "../annotationManager.js";
|
|
3
|
-
import IAppVariantIdHierarchyItem from "../model/appVariantIdHierarchyItem.js";
|
|
3
|
+
import { IAppVariantIdHierarchyItem } from "../model/appVariantIdHierarchyItem.js";
|
|
4
4
|
import { IConfiguration } from "../model/types.js";
|
|
5
5
|
import IProcessor from "./processor.js";
|
|
6
|
+
import { IAdapter } from "../adapters/adapter.js";
|
|
6
7
|
export default class AbapProcessor implements IProcessor {
|
|
7
8
|
private abapRepoManager;
|
|
8
9
|
private configuration;
|
|
9
10
|
private annotationManager;
|
|
10
11
|
constructor(configuration: IConfiguration, abapRepoManager: AbapRepoManager, annotationManager: AnnotationManager);
|
|
11
12
|
getAppVariantIdHierarchy(appId: string): Promise<IAppVariantIdHierarchyItem[]>;
|
|
13
|
+
getAdapter(): IAdapter;
|
|
12
14
|
fetch(repoName: string, _cachebusterToken: string): Promise<Map<string, string>>;
|
|
13
15
|
fetchReuseLib(): Promise<Map<string, string>>;
|
|
14
16
|
validateConfiguration(): void;
|
|
15
|
-
updateLandscapeSpecificContent(baseAppManifest: any, baseAppFiles: Map<string, string>, appVariantId: string, prefix: string): Promise<void>;
|
|
16
17
|
getConfigurationType(): string;
|
|
17
|
-
createAppVariantHierarchyItem(appVariantId: string, version: string): {
|
|
18
|
-
appVariantId: string;
|
|
19
|
-
version: string;
|
|
20
|
-
layer: string;
|
|
21
|
-
};
|
|
22
18
|
}
|
|
@@ -4,9 +4,9 @@ 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 Language from "../model/language.js";
|
|
8
7
|
import { cached } from "../cache/cacheHolder.js";
|
|
9
8
|
import { validateObject } from "../util/commonUtil.js";
|
|
9
|
+
import AbapAdapter from "../adapters/abapAdapter.js";
|
|
10
10
|
export default class AbapProcessor {
|
|
11
11
|
abapRepoManager;
|
|
12
12
|
configuration;
|
|
@@ -19,6 +19,9 @@ export default class AbapProcessor {
|
|
|
19
19
|
getAppVariantIdHierarchy(appId) {
|
|
20
20
|
return this.abapRepoManager.getAppVariantIdHierarchy(appId);
|
|
21
21
|
}
|
|
22
|
+
getAdapter() {
|
|
23
|
+
return new AbapAdapter(this.configuration, this.annotationManager);
|
|
24
|
+
}
|
|
22
25
|
fetch(repoName, _cachebusterToken) {
|
|
23
26
|
return this.abapRepoManager.fetch(repoName);
|
|
24
27
|
}
|
|
@@ -30,23 +33,9 @@ export default class AbapProcessor {
|
|
|
30
33
|
const properties = ["appName"];
|
|
31
34
|
validateObject(this.configuration, properties, "should be specified in ui5.yaml configuration");
|
|
32
35
|
}
|
|
33
|
-
async updateLandscapeSpecificContent(baseAppManifest, baseAppFiles, appVariantId, prefix) {
|
|
34
|
-
const languages = Language.create(this.configuration.languages);
|
|
35
|
-
const files = await this.annotationManager.process(baseAppManifest, languages, appVariantId, prefix);
|
|
36
|
-
if (baseAppFiles) {
|
|
37
|
-
files.forEach((value, key) => baseAppFiles.set(key, value));
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
36
|
getConfigurationType() {
|
|
41
37
|
return "abap";
|
|
42
38
|
}
|
|
43
|
-
createAppVariantHierarchyItem(appVariantId, version) {
|
|
44
|
-
return {
|
|
45
|
-
appVariantId,
|
|
46
|
-
version,
|
|
47
|
-
layer: "VENDOR"
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
39
|
}
|
|
51
40
|
__decorate([
|
|
52
41
|
cached()
|
|
@@ -1,20 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { IAppVariantIdHierarchyItem } from "../model/appVariantIdHierarchyItem.js";
|
|
2
2
|
import { IConfiguration, IReuseLibInfo } from "../model/types.js";
|
|
3
3
|
import IProcessor from "./processor.js";
|
|
4
|
+
import { IAdapter } from "../adapters/adapter.js";
|
|
4
5
|
export default class CFProcessor implements IProcessor {
|
|
5
|
-
|
|
6
|
+
protected configuration: IConfiguration;
|
|
6
7
|
constructor(configuration: IConfiguration);
|
|
7
|
-
|
|
8
|
+
getAdapter(): IAdapter;
|
|
9
|
+
getAppVariantIdHierarchy(appId: string): Promise<IAppVariantIdHierarchyItem[]>;
|
|
8
10
|
fetch(_repoName: string, _cachebusterToken: string): Promise<Map<string, string>>;
|
|
9
11
|
fetchReuseLib(_libName: string, _cachebusterToken: string, lib: IReuseLibInfo): Promise<Map<string, string>>;
|
|
10
12
|
validateConfiguration(): void;
|
|
11
|
-
updateLandscapeSpecificContent(baseAppManifest: any, baseAppFiles: Map<string, string>): Promise<void>;
|
|
12
|
-
private updateXsAppJson;
|
|
13
|
-
private enhanceRoutesWithEndpointAndService;
|
|
14
|
-
private updateCloudPlatform;
|
|
15
13
|
getConfigurationType(): string;
|
|
16
|
-
createAppVariantHierarchyItem(appVariantId: string, version: string): {
|
|
17
|
-
appVariantId: string;
|
|
18
|
-
version: string;
|
|
19
|
-
};
|
|
20
14
|
}
|
|
@@ -7,15 +7,15 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import HTML5RepoManager from "../repositories/html5RepoManager.js";
|
|
8
8
|
import { cached } from "../cache/cacheHolder.js";
|
|
9
9
|
import { validateObject } from "../util/commonUtil.js";
|
|
10
|
-
import
|
|
11
|
-
import { getLogger } from "@ui5/logger";
|
|
12
|
-
import PreviewManager from "../previewManager.js";
|
|
13
|
-
const log = getLogger("@ui5/task-adaptation::CFProcessor");
|
|
10
|
+
import CFAdapter from "../adapters/cfAdapter.js";
|
|
14
11
|
export default class CFProcessor {
|
|
15
12
|
configuration;
|
|
16
13
|
constructor(configuration) {
|
|
17
14
|
this.configuration = configuration;
|
|
18
15
|
}
|
|
16
|
+
getAdapter() {
|
|
17
|
+
return new CFAdapter(this.configuration);
|
|
18
|
+
}
|
|
19
19
|
async getAppVariantIdHierarchy(appId) {
|
|
20
20
|
const metadata = await HTML5RepoManager.getMetadata(this.configuration);
|
|
21
21
|
return [{
|
|
@@ -33,95 +33,9 @@ export default class CFProcessor {
|
|
|
33
33
|
validateConfiguration() {
|
|
34
34
|
validateObject(this.configuration, ["appHostId", "appName", "appVersion"], "should be specified in ui5.yaml configuration");
|
|
35
35
|
}
|
|
36
|
-
async updateLandscapeSpecificContent(baseAppManifest, baseAppFiles) {
|
|
37
|
-
this.updateCloudPlatform(baseAppManifest);
|
|
38
|
-
// Preview uses destinations and does not require xs-app.json updates
|
|
39
|
-
if (!PreviewManager.isPreviewRequested()) {
|
|
40
|
-
await this.updateXsAppJson(baseAppFiles);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
async updateXsAppJson(baseAppFiles) {
|
|
44
|
-
const xsAppJsonContent = baseAppFiles.get("xs-app.json");
|
|
45
|
-
if (!xsAppJsonContent) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
// Also skip if no routes or no routes with a destination property
|
|
49
|
-
const xsAppJson = JSON.parse(xsAppJsonContent);
|
|
50
|
-
if (!Array.isArray(xsAppJson.routes) || !xsAppJson.routes.some((route) => route.destination)) {
|
|
51
|
-
log.verbose(`No routes with 'destination' found in xs-app.json for app '${this.configuration.appName}'. Skipping xs-app.json update.`);
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
const { serviceInstanceName, space } = this.configuration;
|
|
55
|
-
if (!serviceInstanceName) {
|
|
56
|
-
throw new Error(`Service instance name must be specified in ui5.yaml configuration for app '${this.configuration.appName}'`);
|
|
57
|
-
}
|
|
58
|
-
let serviceCredentials;
|
|
59
|
-
try {
|
|
60
|
-
// Get valid service keys with proper endpoints structure
|
|
61
|
-
serviceCredentials = await CFUtil.getOrCreateServiceKeyWithEndpoints(serviceInstanceName, space);
|
|
62
|
-
}
|
|
63
|
-
catch (error) {
|
|
64
|
-
throw new Error(`Failed to get valid service keys for app '${this.configuration.appName}': ${error.message}`);
|
|
65
|
-
}
|
|
66
|
-
if (serviceCredentials) {
|
|
67
|
-
xsAppJson.routes = this.enhanceRoutesWithEndpointAndService(serviceCredentials, xsAppJson.routes);
|
|
68
|
-
baseAppFiles.set("xs-app.json", JSON.stringify(xsAppJson, null, 2));
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
log.info(`No endpoints found for app '${this.configuration.appName}'. xs-app.json will not be updated.`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
enhanceRoutesWithEndpointAndService(serviceCredentials, baseRoutes) {
|
|
75
|
-
const endpoints = serviceCredentials.endpoints;
|
|
76
|
-
// Map destinations to endpoint names
|
|
77
|
-
const destinationToEndpoint = Object.entries(endpoints).reduce((acc, [endpointName, obj]) => {
|
|
78
|
-
if (obj.destination) {
|
|
79
|
-
acc[obj.destination] = endpointName;
|
|
80
|
-
}
|
|
81
|
-
return acc;
|
|
82
|
-
}, {});
|
|
83
|
-
return baseRoutes.map((route) => {
|
|
84
|
-
const endpointName = destinationToEndpoint[route.destination];
|
|
85
|
-
if (endpointName) {
|
|
86
|
-
// There is a matching endpoint: remove destination and add endpoint/service
|
|
87
|
-
const { destination: _destination, ...rest } = route;
|
|
88
|
-
return {
|
|
89
|
-
...rest,
|
|
90
|
-
endpoint: endpointName,
|
|
91
|
-
service: serviceCredentials["sap.cloud.service"],
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
// No match: return route unchanged
|
|
96
|
-
return route;
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
updateCloudPlatform(baseAppManifest) {
|
|
101
|
-
const sapCloudService = baseAppManifest["sap.cloud"]?.service;
|
|
102
|
-
const sapPlatformCf = baseAppManifest["sap.platform.cf"];
|
|
103
|
-
if (sapPlatformCf?.oAuthScopes && sapCloudService) {
|
|
104
|
-
sapPlatformCf.oAuthScopes = sapPlatformCf.oAuthScopes.map((scope) => scope.replace(`$XSAPPNAME.`, `$XSAPPNAME('${sapCloudService}').`));
|
|
105
|
-
}
|
|
106
|
-
if (this.configuration.sapCloudService) {
|
|
107
|
-
if (baseAppManifest["sap.cloud"] == null) {
|
|
108
|
-
baseAppManifest["sap.cloud"] = {};
|
|
109
|
-
}
|
|
110
|
-
baseAppManifest["sap.cloud"].service = this.configuration.sapCloudService;
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
delete baseAppManifest["sap.cloud"];
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
36
|
getConfigurationType() {
|
|
117
37
|
return "cf";
|
|
118
38
|
}
|
|
119
|
-
createAppVariantHierarchyItem(appVariantId, version) {
|
|
120
|
-
return {
|
|
121
|
-
appVariantId,
|
|
122
|
-
version
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
39
|
}
|
|
126
40
|
__decorate([
|
|
127
41
|
cached()
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IAdapter } from "../adapters/adapter.js";
|
|
2
|
+
import { IConfiguration } from "../model/types.js";
|
|
3
|
+
import CFProcessor from "./cfProcessor.js";
|
|
4
|
+
import IProcessor from "./processor.js";
|
|
5
|
+
export default class PreviewProcessor extends CFProcessor implements IProcessor {
|
|
6
|
+
constructor(configuration: IConfiguration);
|
|
7
|
+
getAdapter(): IAdapter;
|
|
8
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import PreviewAdapter from "../adapters/previewAdapter.js";
|
|
2
|
+
import CFProcessor from "./cfProcessor.js";
|
|
3
|
+
export default class PreviewProcessor extends CFProcessor {
|
|
4
|
+
constructor(configuration) {
|
|
5
|
+
super(configuration);
|
|
6
|
+
}
|
|
7
|
+
getAdapter() {
|
|
8
|
+
return new PreviewAdapter(this.configuration);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=previewProcessor.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import IAppVariantIdHierarchyItem from "../model/appVariantIdHierarchyItem.js";
|
|
1
|
+
import { IAppVariantIdHierarchyItem } from "../model/appVariantIdHierarchyItem.js";
|
|
2
2
|
import { IConfiguration, IReuseLibInfo } from "../model/types.js";
|
|
3
|
+
import { IAdapter } from "../adapters/adapter.js";
|
|
3
4
|
export default interface IProcessor {
|
|
4
5
|
getAppVariantIdHierarchy(appId: string): Promise<IAppVariantIdHierarchyItem[]>;
|
|
6
|
+
getAdapter(): IAdapter;
|
|
5
7
|
fetch(repoName: string, cachebusterToken: string): Promise<Map<string, string>>;
|
|
6
8
|
fetchReuseLib(repoName: string, cachebusterToken: string, lib: IReuseLibInfo): Promise<Map<string, string>>;
|
|
7
|
-
createAppVariantHierarchyItem(appVariantId: string, version: string): void;
|
|
8
|
-
updateLandscapeSpecificContent(baseAppManifest: any, baseAppFiles: Map<string, string>, appVariantId: string, prefix: string): Promise<void>;
|
|
9
9
|
}
|
|
10
10
|
export declare function determineProcessor(configuration: IConfiguration): IProcessor;
|
|
@@ -2,6 +2,7 @@ import AbapProcessor from "./abapProcessor.js";
|
|
|
2
2
|
import AbapRepoManager from "../repositories/abapRepoManager.js";
|
|
3
3
|
import AnnotationManager from "../annotationManager.js";
|
|
4
4
|
import CFProcessor from "./cfProcessor.js";
|
|
5
|
+
import PreviewProcessor from "./previewProcessor.js";
|
|
5
6
|
export function determineProcessor(configuration) {
|
|
6
7
|
const abapRepoManager = new AbapRepoManager(configuration);
|
|
7
8
|
const annotationManager = new AnnotationManager(configuration, abapRepoManager);
|
|
@@ -9,6 +10,11 @@ export function determineProcessor(configuration) {
|
|
|
9
10
|
new CFProcessor(configuration),
|
|
10
11
|
new AbapProcessor(configuration, abapRepoManager, annotationManager)
|
|
11
12
|
];
|
|
13
|
+
if (isPreviewMode()) {
|
|
14
|
+
const processor = new PreviewProcessor(configuration);
|
|
15
|
+
processor.validateConfiguration();
|
|
16
|
+
return processor;
|
|
17
|
+
}
|
|
12
18
|
let processor = processors.find(processor => processor.getConfigurationType() === configuration.type);
|
|
13
19
|
if (processor) {
|
|
14
20
|
processor.validateConfiguration();
|
|
@@ -27,4 +33,7 @@ export function determineProcessor(configuration) {
|
|
|
27
33
|
}
|
|
28
34
|
throw new Error("ui5.yaml configuration should correspond either ABAP or SAP BTP landscape");
|
|
29
35
|
}
|
|
36
|
+
function isPreviewMode() {
|
|
37
|
+
return process.env.ADP_BUILDER_MODE === "preview";
|
|
38
|
+
}
|
|
30
39
|
//# sourceMappingURL=processor.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IConfiguration, IMetadata } from "../model/types.js";
|
|
2
2
|
import AbapProvider from "./abapProvider.js";
|
|
3
|
-
import IAppVariantIdHierarchyItem from "../model/appVariantIdHierarchyItem.js";
|
|
3
|
+
import { IAppVariantIdHierarchyItem } from "../model/appVariantIdHierarchyItem.js";
|
|
4
4
|
export default class AbapRepoManager {
|
|
5
5
|
private configuration;
|
|
6
6
|
private abapProvider;
|
|
@@ -30,6 +30,12 @@ export default class HTML5RepoManager {
|
|
|
30
30
|
const spaceGuid = await CFUtil.getSpaceGuid(configuration?.space);
|
|
31
31
|
const credentials = await this.getHTML5Credentials(spaceGuid);
|
|
32
32
|
const token = await this.getToken(credentials);
|
|
33
|
+
if (!token || token.length === 0) {
|
|
34
|
+
throw new Error("Failed to obtain HTML5 Repo token");
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
log.verbose("Obtained HTML5 Repo token");
|
|
38
|
+
}
|
|
33
39
|
return {
|
|
34
40
|
token,
|
|
35
41
|
baseUri: credentials.uri
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ServiceCredentials } from "../../model/types.js";
|
|
2
|
+
export declare const XSAPP_JSON_FILENAME = "xs-app.json";
|
|
3
|
+
/**
|
|
4
|
+
* Merges multiple xs-app.json contents into one. AppVariant and Reuse Library
|
|
5
|
+
* xs-app.json files come first, base app xs-app.json last. Routes from all
|
|
6
|
+
* files are concatenated.
|
|
7
|
+
* @param xsAppFiles Array of xs-app.json file contents as strings
|
|
8
|
+
* @returns Merged xs-app.json content as a string, or undefined if no files
|
|
9
|
+
* were provided
|
|
10
|
+
*/
|
|
11
|
+
export declare function merge(xsAppFiles: string[]): string | undefined;
|
|
12
|
+
export declare function enhanceRoutesWithEndpointAndService(xsAppJsonContent: string, serviceCredentials: ServiceCredentials): string;
|
|
13
|
+
export declare function enhanceRoutes(serviceCredentials: ServiceCredentials, baseRoutes: any): any;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { getLogger } from "@ui5/logger";
|
|
2
|
+
const log = getLogger("@ui5/task-adaptation::XSAppJsonUtil");
|
|
3
|
+
export const XSAPP_JSON_FILENAME = "xs-app.json";
|
|
4
|
+
/**
|
|
5
|
+
* Merges multiple xs-app.json contents into one. AppVariant and Reuse Library
|
|
6
|
+
* xs-app.json files come first, base app xs-app.json last. Routes from all
|
|
7
|
+
* files are concatenated.
|
|
8
|
+
* @param xsAppFiles Array of xs-app.json file contents as strings
|
|
9
|
+
* @returns Merged xs-app.json content as a string, or undefined if no files
|
|
10
|
+
* were provided
|
|
11
|
+
*/
|
|
12
|
+
export function merge(xsAppFiles) {
|
|
13
|
+
if (xsAppFiles.length === 0) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (xsAppFiles.length === 1) {
|
|
17
|
+
return xsAppFiles[0];
|
|
18
|
+
}
|
|
19
|
+
// Start with empty xs-app.json
|
|
20
|
+
const merged = {
|
|
21
|
+
authenticationMethod: "none",
|
|
22
|
+
routes: []
|
|
23
|
+
};
|
|
24
|
+
for (const xsAppInfoContent of xsAppFiles) {
|
|
25
|
+
let parsed;
|
|
26
|
+
try {
|
|
27
|
+
parsed = JSON.parse(xsAppInfoContent);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
throw new Error(`Failed to parse xs-app.json content: ${error instanceof Error ? error.message : String(error)}`);
|
|
31
|
+
}
|
|
32
|
+
const { authenticationMethod, routes, welcomeFile } = parsed;
|
|
33
|
+
if (merged.welcomeFile === undefined && welcomeFile) {
|
|
34
|
+
merged.welcomeFile = welcomeFile;
|
|
35
|
+
}
|
|
36
|
+
if (merged.authenticationMethod === "none" && authenticationMethod) {
|
|
37
|
+
merged.authenticationMethod = authenticationMethod;
|
|
38
|
+
}
|
|
39
|
+
if (Array.isArray(routes)) {
|
|
40
|
+
merged.routes = merged.routes.concat(routes);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return JSON.stringify(merged, null, 4);
|
|
44
|
+
}
|
|
45
|
+
export function enhanceRoutesWithEndpointAndService(xsAppJsonContent, serviceCredentials) {
|
|
46
|
+
// Also skip if no routes or no routes with a destination property
|
|
47
|
+
const xsAppJson = JSON.parse(xsAppJsonContent);
|
|
48
|
+
if (!Array.isArray(xsAppJson.routes) || !xsAppJson.routes.some((route) => route.destination)) {
|
|
49
|
+
log.verbose(`No routes with 'destination' found in xs-app.json. Skipping xs-app.json update.`);
|
|
50
|
+
return xsAppJsonContent;
|
|
51
|
+
}
|
|
52
|
+
xsAppJson.routes = enhanceRoutes(serviceCredentials, xsAppJson.routes);
|
|
53
|
+
return JSON.stringify(xsAppJson, null, 4);
|
|
54
|
+
}
|
|
55
|
+
export function enhanceRoutes(serviceCredentials, baseRoutes) {
|
|
56
|
+
const endpoints = serviceCredentials.endpoints;
|
|
57
|
+
// Map destinations to endpoint names
|
|
58
|
+
const destinationToEndpoint = Object.entries(endpoints).reduce((acc, [endpointName, obj]) => {
|
|
59
|
+
if (obj && typeof obj === "object" && obj.destination) {
|
|
60
|
+
acc[obj.destination] = endpointName;
|
|
61
|
+
}
|
|
62
|
+
return acc;
|
|
63
|
+
}, {});
|
|
64
|
+
return baseRoutes.map((route) => {
|
|
65
|
+
const endpointName = destinationToEndpoint[route.destination];
|
|
66
|
+
if (endpointName) {
|
|
67
|
+
// There is a matching endpoint: remove destination and add endpoint/service
|
|
68
|
+
const { destination: _destination, ...rest } = route;
|
|
69
|
+
return {
|
|
70
|
+
...rest,
|
|
71
|
+
endpoint: endpointName,
|
|
72
|
+
service: serviceCredentials["sap.cloud.service"],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// No match: return route unchanged
|
|
77
|
+
return route;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=xsAppJsonUtil.js.map
|
package/dist/util/cfUtil.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ICreateServiceInstanceParams, IGetServiceInstanceParams, IResource, IServiceKeys } from "../model/types.js";
|
|
1
|
+
import { ICreateServiceInstanceParams, IGetServiceInstanceParams, IResource, IServiceKeys, ServiceCredentials } from "../model/types.js";
|
|
2
2
|
export default class CFUtil {
|
|
3
3
|
/**
|
|
4
4
|
* Get or create service keys for service instance found by query
|
|
@@ -26,7 +26,7 @@ export default class CFUtil {
|
|
|
26
26
|
* @private
|
|
27
27
|
* @static
|
|
28
28
|
* @param {string} serviceInstanceGuid the service instance guid
|
|
29
|
-
* @return {Promise<
|
|
29
|
+
* @return {Promise<ServiceCredentials | null>} the first service key with valid endpoints, or null if none found
|
|
30
30
|
* @memberof CFUtil
|
|
31
31
|
*/
|
|
32
32
|
private static getServiceKeyWithValidEndpoints;
|
|
@@ -39,7 +39,7 @@ export default class CFUtil {
|
|
|
39
39
|
* @return {Promise<any>} promise with service key credentials
|
|
40
40
|
* @memberof CFUtil
|
|
41
41
|
*/
|
|
42
|
-
static getOrCreateServiceKeyWithEndpoints(serviceInstanceName: string, spaceGuid?: string): Promise<
|
|
42
|
+
static getOrCreateServiceKeyWithEndpoints(serviceInstanceName: string, spaceGuid?: string): Promise<ServiceCredentials | undefined>;
|
|
43
43
|
/**
|
|
44
44
|
* Check if endpoints object has at least one property that is an object
|
|
45
45
|
* @private
|
package/dist/util/cfUtil.js
CHANGED
|
@@ -178,7 +178,7 @@ export default class CFUtil {
|
|
|
178
178
|
* @private
|
|
179
179
|
* @static
|
|
180
180
|
* @param {string} serviceInstanceGuid the service instance guid
|
|
181
|
-
* @return {Promise<
|
|
181
|
+
* @return {Promise<ServiceCredentials | null>} the first service key with valid endpoints, or null if none found
|
|
182
182
|
* @memberof CFUtil
|
|
183
183
|
*/
|
|
184
184
|
static async getServiceKeyWithValidEndpoints(serviceInstanceGuid) {
|
package/dist/util/filesUtil.d.ts
CHANGED
|
@@ -8,9 +8,10 @@ export default class FilesUtil {
|
|
|
8
8
|
* @returns A map of renamed files
|
|
9
9
|
*/
|
|
10
10
|
static rename(files: ReadonlyMap<string, string>, references: Map<string, string>): ReadonlyMap<string, string>;
|
|
11
|
+
private static getManifestSAPUI5DependencyIds;
|
|
11
12
|
private static getI18nPropertyKeys;
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
14
|
-
* We might rename appVariantIdHierarchy, so we restore
|
|
15
|
+
* We might rename appVariantIdHierarchy and dependencies, so we restore them after the renaming.
|
|
15
16
|
*/
|
|
16
|
-
export declare function
|
|
17
|
+
export declare function restoreWhatShouldntBeRenamed(): (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => void;
|
package/dist/util/filesUtil.js
CHANGED
|
@@ -32,7 +32,10 @@ export default class FilesUtil {
|
|
|
32
32
|
*/
|
|
33
33
|
static rename(files, references) {
|
|
34
34
|
const IGNORE_EXTENSIONS = [".properties"];
|
|
35
|
-
const ignoreInString =
|
|
35
|
+
const ignoreInString = [
|
|
36
|
+
...this.getI18nPropertyKeys(files),
|
|
37
|
+
...this.getManifestSAPUI5DependencyIds(files)
|
|
38
|
+
];
|
|
36
39
|
return new Map(Array.from(files, ([filename, content]) => {
|
|
37
40
|
if (!IGNORE_EXTENSIONS.some(ext => filename.endsWith(ext))) {
|
|
38
41
|
// 5p. We pass replacements as ignores since we don't want to
|
|
@@ -45,6 +48,19 @@ export default class FilesUtil {
|
|
|
45
48
|
return [filename, content];
|
|
46
49
|
}));
|
|
47
50
|
}
|
|
51
|
+
static getManifestSAPUI5DependencyIds(files) {
|
|
52
|
+
const manifestFile = files.get("manifest.json");
|
|
53
|
+
if (manifestFile) {
|
|
54
|
+
const manifest = JSON.parse(manifestFile);
|
|
55
|
+
const dependencies = manifest["sap.ui5"]?.dependencies;
|
|
56
|
+
if (dependencies) {
|
|
57
|
+
const libs = dependencies.libs ? Object.keys(dependencies.libs) : [];
|
|
58
|
+
const components = dependencies.components ? Object.keys(dependencies.components) : [];
|
|
59
|
+
return [...libs, ...components];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
48
64
|
static getI18nPropertyKeys(files) {
|
|
49
65
|
const keys = new Set();
|
|
50
66
|
files.forEach((content, filename) => {
|
|
@@ -62,12 +78,12 @@ export default class FilesUtil {
|
|
|
62
78
|
}
|
|
63
79
|
}
|
|
64
80
|
__decorate([
|
|
65
|
-
|
|
81
|
+
restoreWhatShouldntBeRenamed()
|
|
66
82
|
], FilesUtil, "rename", null);
|
|
67
83
|
/**
|
|
68
|
-
* We might rename appVariantIdHierarchy, so we restore
|
|
84
|
+
* We might rename appVariantIdHierarchy and dependencies, so we restore them after the renaming.
|
|
69
85
|
*/
|
|
70
|
-
export function
|
|
86
|
+
export function restoreWhatShouldntBeRenamed() {
|
|
71
87
|
return function (_target, _propertyKey, descriptor) {
|
|
72
88
|
const handlers = [new ManifestRenamingHandler()];
|
|
73
89
|
const originalValue = descriptor.value;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default class FsUtil {
|
|
2
|
+
static readInProject(filepath: string): Promise<string>;
|
|
3
|
+
/**
|
|
4
|
+
* Check whether a file or directory exists (non-throwing).
|
|
5
|
+
* @param filePath Absolute or relative path
|
|
6
|
+
* @returns true if the path exists, false if not
|
|
7
|
+
*/
|
|
8
|
+
private static fileExists;
|
|
9
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import fs from "fs/promises";
|
|
2
|
+
import path from "path";
|
|
3
|
+
export default class FsUtil {
|
|
4
|
+
/*
|
|
5
|
+
* Read the file by filepath from the project root (folder where 'webapp',
|
|
6
|
+
* 'package.json', 'ui5.yaml' located).
|
|
7
|
+
* @param filepath The relative file path from the project root (e.g. 'ui5AppInfo.json').
|
|
8
|
+
* @returns A promise that resolves to the file content as a string.
|
|
9
|
+
*/
|
|
10
|
+
static async readInProject(filepath) {
|
|
11
|
+
try {
|
|
12
|
+
return await fs.readFile(path.join(process.cwd(), filepath), "utf-8");
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
const isProjectRoot = await FsUtil.fileExists(path.join(process.cwd(), "ui5.yaml"));
|
|
16
|
+
if (!isProjectRoot) {
|
|
17
|
+
throw new Error(`Please make sure that build has been started from the project root: ${error?.message ?? ""}`);
|
|
18
|
+
}
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Check whether a file or directory exists (non-throwing).
|
|
24
|
+
* @param filePath Absolute or relative path
|
|
25
|
+
* @returns true if the path exists, false if not
|
|
26
|
+
*/
|
|
27
|
+
static async fileExists(filePath) {
|
|
28
|
+
try {
|
|
29
|
+
await fs.access(filePath);
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
if (e?.code === "ENOENT") {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
throw e;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=fsUtil.js.map
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import path from "path";
|
|
2
1
|
import { isManifestChange } from "../commonUtil.js";
|
|
3
2
|
const EXT_DIR = "ext/";
|
|
4
3
|
const CHANGES_DIR = "changes/";
|
|
@@ -62,9 +61,9 @@ export const moveFile = (filename, content, prefix, id) => {
|
|
|
62
61
|
let renamingPath = new Map();
|
|
63
62
|
if (shouldMove(filename, content)) {
|
|
64
63
|
const [dir, ...rest] = filename.split("/");
|
|
65
|
-
newFilename =
|
|
64
|
+
newFilename = [dir, prefix, ...rest].join("/");
|
|
66
65
|
const restWOExtPath = getPathWithoutExtensions(filename);
|
|
67
|
-
renamingPath.set(restWOExtPath,
|
|
66
|
+
renamingPath.set(restWOExtPath, [prefix, restWOExtPath].join("/"));
|
|
68
67
|
}
|
|
69
68
|
if (shouldNamespaceRenamed(filename)) {
|
|
70
69
|
const namespaceMatch = nameSpaceRegex.exec(content.trim());
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sets a value at a dot-separated path, creating missing objects along the way.
|
|
3
|
+
* @example
|
|
4
|
+
* const root: any = {};
|
|
5
|
+
* setObjectPath(root, "a.b.c", 5);
|
|
6
|
+
* // root.a.b.c === 5
|
|
7
|
+
* @example
|
|
8
|
+
* setObjectPath(root, ["x", "y"], true);
|
|
9
|
+
* // root.x.y === true
|
|
10
|
+
*/
|
|
11
|
+
export declare function set(obj: any, pathValue: string | string[], value: unknown): void;
|
|
12
|
+
/**
|
|
13
|
+
* Ensures a default value is set at the path and returns the stored value.
|
|
14
|
+
* @example
|
|
15
|
+
* const root: any = { a: { b: { c: [1] } } };
|
|
16
|
+
* get(root, "a.b.c", []).unshift(0);
|
|
17
|
+
* // root.a.b.c === [0, 1]
|
|
18
|
+
*/
|
|
19
|
+
export declare function get<T>(obj: any, pathValue: string | string[], defaultValue: T): T;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Splits a dot-separated path or clones an array path.
|
|
3
|
+
* @example
|
|
4
|
+
* splitObjectPath("a.b.c"); // ["a", "b", "c"]
|
|
5
|
+
* @example
|
|
6
|
+
* splitObjectPath(["a", "b"]); // ["a", "b"]
|
|
7
|
+
*/
|
|
8
|
+
function splitObjectPath(pathValue) {
|
|
9
|
+
return Array.isArray(pathValue) ? pathValue.slice() : pathValue.split(".");
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Ensures a nested object path exists and returns the last object in the chain.
|
|
13
|
+
* Overwrites existing non-object segments with plain objects.
|
|
14
|
+
* @example
|
|
15
|
+
* const root: any = {};
|
|
16
|
+
* createObjectPath(root, ["a", "b"]); // root.a.b is created
|
|
17
|
+
*/
|
|
18
|
+
function createObjectPath(obj, pathValue) {
|
|
19
|
+
for (const segment of pathValue) {
|
|
20
|
+
if (obj[segment] === null || (obj[segment] !== undefined && typeof obj[segment] !== "object" && typeof obj[segment] !== "function")) {
|
|
21
|
+
obj[segment] = {};
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
obj[segment] = obj[segment] || {};
|
|
25
|
+
}
|
|
26
|
+
obj = obj[segment];
|
|
27
|
+
}
|
|
28
|
+
return obj;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Sets a value at a dot-separated path, creating missing objects along the way.
|
|
32
|
+
* @example
|
|
33
|
+
* const root: any = {};
|
|
34
|
+
* setObjectPath(root, "a.b.c", 5);
|
|
35
|
+
* // root.a.b.c === 5
|
|
36
|
+
* @example
|
|
37
|
+
* setObjectPath(root, ["x", "y"], true);
|
|
38
|
+
* // root.x.y === true
|
|
39
|
+
*/
|
|
40
|
+
export function set(obj, pathValue, value) {
|
|
41
|
+
const parts = splitObjectPath(pathValue);
|
|
42
|
+
const lastSegment = parts.pop();
|
|
43
|
+
const target = createObjectPath(obj, parts);
|
|
44
|
+
target[lastSegment] = value;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Ensures a default value is set at the path and returns the stored value.
|
|
48
|
+
* @example
|
|
49
|
+
* const root: any = { a: { b: { c: [1] } } };
|
|
50
|
+
* get(root, "a.b.c", []).unshift(0);
|
|
51
|
+
* // root.a.b.c === [0, 1]
|
|
52
|
+
*/
|
|
53
|
+
export function get(obj, pathValue, defaultValue) {
|
|
54
|
+
const parts = splitObjectPath(pathValue);
|
|
55
|
+
const lastSegment = parts.pop();
|
|
56
|
+
const target = createObjectPath(obj, parts);
|
|
57
|
+
if (target[lastSegment] === undefined) {
|
|
58
|
+
target[lastSegment] = defaultValue;
|
|
59
|
+
}
|
|
60
|
+
return target[lastSegment];
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=objectPath.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { IRenamingHandler } from "./renamingHandler.js";
|
|
2
|
+
export default abstract class JsonRenamingHandler implements IRenamingHandler {
|
|
3
|
+
private original;
|
|
4
|
+
protected abstract filePath: string;
|
|
5
|
+
protected abstract jsonPathsToRestore: string[];
|
|
6
|
+
before(files: ReadonlyMap<string, string>): void;
|
|
7
|
+
after(files: Map<string, string>): void;
|
|
8
|
+
protected store(obj: any, path: string): void;
|
|
9
|
+
protected restore(obj: any): void;
|
|
10
|
+
private getByPath;
|
|
11
|
+
private setByPath;
|
|
12
|
+
}
|