@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.
Files changed (74) hide show
  1. package/CHANGELOG.md +28 -9
  2. package/dist/adapters/abapAdapter.d.ts +14 -0
  3. package/dist/adapters/abapAdapter.js +45 -0
  4. package/dist/adapters/adapter.d.ts +8 -0
  5. package/dist/adapters/adapter.js +2 -0
  6. package/dist/adapters/cfAdapter.d.ts +12 -0
  7. package/dist/adapters/cfAdapter.js +46 -0
  8. package/dist/adapters/commands/addAppVariantIdHierarchyCommand.d.ts +7 -0
  9. package/dist/adapters/commands/addAppVariantIdHierarchyCommand.js +17 -0
  10. package/dist/adapters/commands/applyDescriptorChangesCommand.d.ts +10 -0
  11. package/dist/adapters/commands/applyDescriptorChangesCommand.js +43 -0
  12. package/dist/adapters/commands/command.d.ts +84 -0
  13. package/dist/adapters/commands/command.js +108 -0
  14. package/dist/adapters/commands/downloadAnnotationsCommand.d.ts +12 -0
  15. package/dist/adapters/commands/downloadAnnotationsCommand.js +26 -0
  16. package/dist/{util/i18nMerger.d.ts → adapters/commands/i18nPropertiesMergeCommand.d.ts} +13 -10
  17. package/dist/{util/i18nMerger.js → adapters/commands/i18nPropertiesMergeCommand.js} +30 -27
  18. package/dist/adapters/commands/setAppVariantIdCommand.d.ts +7 -0
  19. package/dist/adapters/commands/setAppVariantIdCommand.js +15 -0
  20. package/dist/adapters/commands/updateCloudDevAdaptationCommand.d.ts +4 -0
  21. package/dist/adapters/commands/updateCloudDevAdaptationCommand.js +11 -0
  22. package/dist/adapters/commands/updateCloudPlatformCommand.d.ts +6 -0
  23. package/dist/adapters/commands/updateCloudPlatformCommand.js +23 -0
  24. package/dist/adapters/commands/updateComponentNameCommand.d.ts +6 -0
  25. package/dist/adapters/commands/updateComponentNameCommand.js +13 -0
  26. package/dist/adapters/commands/xsAppJsonEnhanceRoutesCommand.d.ts +7 -0
  27. package/dist/adapters/commands/xsAppJsonEnhanceRoutesCommand.js +36 -0
  28. package/dist/adapters/commands/xsAppJsonMergeCommand.d.ts +5 -0
  29. package/dist/adapters/commands/xsAppJsonMergeCommand.js +17 -0
  30. package/dist/adapters/previewAdapter.d.ts +6 -0
  31. package/dist/adapters/previewAdapter.js +8 -0
  32. package/dist/appVariantManager.js +3 -0
  33. package/dist/baseAppManager.d.ts +0 -8
  34. package/dist/baseAppManager.js +3 -69
  35. package/dist/bundle.js +37 -35
  36. package/dist/cache/cacheHolder.js +9 -4
  37. package/dist/index.js +7 -3
  38. package/dist/model/appVariantIdHierarchyItem.d.ts +6 -1
  39. package/dist/model/types.d.ts +6 -0
  40. package/dist/previewManager.js +16 -23
  41. package/dist/processors/abapProcessor.d.ts +3 -7
  42. package/dist/processors/abapProcessor.js +4 -15
  43. package/dist/processors/cfProcessor.d.ts +5 -11
  44. package/dist/processors/cfProcessor.js +4 -90
  45. package/dist/processors/previewProcessor.d.ts +8 -0
  46. package/dist/processors/previewProcessor.js +11 -0
  47. package/dist/processors/processor.d.ts +3 -3
  48. package/dist/processors/processor.js +9 -0
  49. package/dist/repositories/abapRepoManager.d.ts +1 -1
  50. package/dist/repositories/html5RepoManager.js +6 -0
  51. package/dist/util/cf/xsAppJsonUtil.d.ts +13 -0
  52. package/dist/util/cf/xsAppJsonUtil.js +81 -0
  53. package/dist/util/cfUtil.d.ts +3 -3
  54. package/dist/util/cfUtil.js +1 -1
  55. package/dist/util/filesUtil.d.ts +3 -2
  56. package/dist/util/filesUtil.js +20 -4
  57. package/dist/util/fsUtil.d.ts +9 -0
  58. package/dist/util/fsUtil.js +40 -0
  59. package/dist/util/movingHandler/changeFileMoveHandler.js +2 -3
  60. package/dist/util/objectPath.d.ts +19 -0
  61. package/dist/util/objectPath.js +62 -0
  62. package/dist/util/renamingHandlers/jsonRenamingHandler.d.ts +12 -0
  63. package/dist/util/renamingHandlers/jsonRenamingHandler.js +34 -0
  64. package/dist/util/renamingHandlers/manifestRenamingHandler.d.ts +4 -5
  65. package/dist/util/renamingHandlers/manifestRenamingHandler.js +7 -18
  66. package/dist/util/requestUtil.d.ts +1 -1
  67. package/dist/util/requestUtil.js +5 -2
  68. package/dist/util/resourceUtil.d.ts +0 -7
  69. package/dist/util/resourceUtil.js +0 -36
  70. package/package.json +3 -2
  71. package/dist/util/movingHandler/fileMoveHandler.d.ts +0 -8
  72. package/dist/util/movingHandler/fileMoveHandler.js +0 -77
  73. package/scripts/publish.ts +0 -256
  74. 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 IAppInfo from "../model/appVariantIdHierarchyItem.js";
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
- private configuration;
6
+ protected configuration: IConfiguration;
6
7
  constructor(configuration: IConfiguration);
7
- getAppVariantIdHierarchy(appId: string): Promise<IAppInfo[]>;
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 CFUtil from "../util/cfUtil.js";
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
@@ -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<any>} the first service key with valid endpoints, or null if none found
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<any>;
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
@@ -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<any>} the first service key with valid endpoints, or null if none found
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) {
@@ -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 it after the renaming.
15
+ * We might rename appVariantIdHierarchy and dependencies, so we restore them after the renaming.
15
16
  */
16
- export declare function restoreThatShouldntBeRenamed(): (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => void;
17
+ export declare function restoreWhatShouldntBeRenamed(): (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => void;
@@ -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 = this.getI18nPropertyKeys(files);
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
- restoreThatShouldntBeRenamed()
81
+ restoreWhatShouldntBeRenamed()
66
82
  ], FilesUtil, "rename", null);
67
83
  /**
68
- * We might rename appVariantIdHierarchy, so we restore it after the renaming.
84
+ * We might rename appVariantIdHierarchy and dependencies, so we restore them after the renaming.
69
85
  */
70
- export function restoreThatShouldntBeRenamed() {
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 = path.join(dir, prefix, rest.join("/"));
64
+ newFilename = [dir, prefix, ...rest].join("/");
66
65
  const restWOExtPath = getPathWithoutExtensions(filename);
67
- renamingPath.set(restWOExtPath, path.join(prefix, 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
+ }